It probably sounds stupid, because it's likely to have been done hundreds of times before already. But I was trying out a Facebook app version of Freecell that had omitted some important key features of this game that has been a staple item of every Microsoft Windows PC since version 3.1 or so. So in my opinion, that Facebook app is broken. Thus if I can make a version of Freecell that works correctly, then I know other people can. And since there's been versions of it since DOS and Win3.1 days, it's not like it's impossible to implement all the rules correctly.

The tricky part of this game is deducting the rules from a programmatic logic standpoint. The problem is that I'm normally not a programmer. So this is a simple logic puzzle and a break from my normal routine. Let's try to think of how the thing works...

First is the layout:

You have four free cells, and you have four open dump cells (Officially its called a foundation, but since I consider it dumping cards out of the game, that's what I've called it.), then you have the cards that get laid out on the table, and you count any empty spaces on the table as an extra free cell. You have eight columns of cards laid out on the table in a random cascade, face up. And generally it's the cards from the bottom (but not only the bottom - important!) of a cascade that are put into play or dumped into the foundation squares.

The actual rules can be found at Wikipedia. So it's known what we have to work with.

Now the first thing to do is initially randomize the cards. This will involve a loop that populates an array. We know we have 52 cards in a standard deck. So we know we need a list that's 52 values long, and contains non-repeating values between 1 and 52. (Non-repeating is important, because there is only one of each card of a given suit and value.) So we use a loop that populates the array. The loop generates a random number between 1 and 52. Then it checks the array to see if the random number matches any already on the array. If there is a match, it goes and generates a new random number and tries again. If there is no match, then it adds the new number to the array. And it keeps doing this until all 52 positions of the array are filled. Easy peasy, right?

Next thing we do... Lay out the cards on the table. This is trickier. I'm thinking of using setting depths (if I recall actionscript correctly) and placing each row across. Since we have the cards in a nice random order from the previous routine, we just populate the table (in more than one way) by drawing from the array. Going across 8 columns, and then down to the next row (and a higher depth), until all 52 cards are used.

Since this is done programmatically, we also need some rules for the suits of the cards. Basically since a simple index number between 1 and 52 is the easiest and most obvious way to identify a card, that's what was done already if you haven't figured it out. But we also need to associate the card's index value with it's suit and it's color. Since I went with diamonds, spades, hearts, clubs as the order of suits, this is how associated variable values are figured out. Index numbers 1-13, diamonds. Index 14-26, spades. Index 27-39, hearts. Index 40-52, clubs. Likewise red-black, red-black. So by pulling up any index number, the function automagically lets you know what the card is. And some simple if-greater than statements and some math routines gives the value from the index number. So now we get the traditional cards suits, colors, and values based upon the index number. And again index numbers are what we use to pick and label any of the cards program-wise.

The easiest rule is for the free cells, thus the name of this solitaire card game. Any card may be placed upon an unoccupied free cell. And no other cards may move on an occupied cell. And any card in the "free" cell, may be put back into play on the table or into the dump (foundation) cells.

What's next? We have the four "dump" foundation places. The rules for dumping cards into the foundation is why we needed that variable that "knows" the suit. So we got to make some if-then statements as some rules. If foundation is empty, an ace (1, 14, 27, and 40 from the index) of any suit may go there. If a card of any suit is in the slot, then check that the suits match. If not, disallow the move. Next check to see if the value of the card being placed is that of the lower card +1. If not, then also disallow the move. Once a card is placed into a foundation position, it's no longer allowed in play.

After that, we need the rest of the rules. Which is tricker to implement. On the table, an empy position can be used by any card. Then if a card is in a playable spot, only a card of an alternate color and a value lower by -1 may be placed on it. However the tricky thing to implement is the moving of stacks of cards. (And this is where the Facebook app that inspired the idea is broken.) If you have a stack of alternating cards in downward order, then entire stacks of cards are playable based on the value of the topmost card. But the playable topmost card of a stack is determined by number of free cells and open columns on available the table. The number of cards that can be moved as a stack are 1 + open columns + free cells. (There's also some programmatic trick in the MS version that anticipates some other moves and allows even more cards, depending on how many table columns are empty.)

The tricky thing is figuring out how to keep stacks together. I'll probably have to to assign variables that tell which row and column a card is currently placed in on the table. Then it's a matter of doing some routine that swaps the depths for all the cards in play so they layout properly from a visual perspective when moved. Scripting is fun (*half-sarcastic lol*), isn't it?

And once all cards are played from the table and free cells and into the foundation cells, the game is a win. If no moves are possible to clear the table (I've still got to figure out how that works programatically, I think I'll just have a manual button in my first implementation), then the game is a loss.

I think I'll give this a shot. I already did the card graphics. Now it's time to start digging into my books and reviewing the actionscript stuff. Other things to add are some stats. Total plays, wins, losses, and win/loss ratio. Maybe some time stats too, like fastest game and average play time. (If other freecell players are like I am, they could care less about other ways of scoring.) I'm also thinking of throwing some quirky goodies into the game, that spoofs the king icon in the MS version. Maybe even have it talk and say random insults when a move isn't allowed, just to make it unique and a bit more fun.

## Saturday, September 12, 2009

Subscribe to:
Posts (Atom)