The first C version I wrote was not identical to the Perl version algorithmically. As some things were more accessible in C than they were in Perl (or vice versa), I was able to take advantage of them (or was unable to).
A card was represented as a C structure which contained two elements of type short, one representing the rank of the card and the other its suit:
struct struct_card_t { short card_num; /* card_num is the rank */ short deck; /* I erroneously referred to the suit as a deck */ }; typedef struct struct_card_t card_t;
A column was represented as a structure containing an array of 19 cards (the maximal number that can be present in a column in a game of freecell), preceded by an int that specified the number of cards present:
struct struct_stack_t { int num_cards; card_t cards[19]; }; typedef struct struct_stack_t fc_stack_t;
The structure representing a board layout contained 8 column structures like that, 4 cards for the freecells and 4 integers representing the rank of the cards in the foundations.
struct struct_state_t { fc_stack_t stacks[8]; card_t freecells[4]; int decks[4]; /* I also called the foundations decks. :-) */ }; typedef struct struct_state_t state_t;
The code also contained several macros that were used to
manipulate this data and perform actions like querying cards,
and states, and modifying them. For instance,
stack_len(
retrieved the length of the column with the index
state
s
)s
that belonged to the state
state
. As another example, the
macro pop_stack_card
was defined as
follows:
#define pop_stack_card(state, s, into) \ into = (state).stacks[(s)].cards[(state).stacks[(s)].num_cards-1]; \ (state).stacks[(s)].cards[(state).stacks[(s)].num_cards-1] = empty_card; \ (state).stacks[(s)].num_cards--;
Note that the columns inside a state were kept sorted according to a lexicographic order, in order to avoid a situation where two states that are identical except for a different order of their columns.