diff options
Diffstat (limited to 'kpat/freecell-solver/simpsim.c')
-rw-r--r-- | kpat/freecell-solver/simpsim.c | 1716 |
1 files changed, 1716 insertions, 0 deletions
diff --git a/kpat/freecell-solver/simpsim.c b/kpat/freecell-solver/simpsim.c new file mode 100644 index 00000000..f603ba39 --- /dev/null +++ b/kpat/freecell-solver/simpsim.c @@ -0,0 +1,1716 @@ +/* + * simpsim.c - a module that contains Simple Simon Moves. + * + * Written by Shlomi Fish (shlomif@vipe.technion.ac.il), 2001 + * + * This file is in the public domain (it's uncopyrighted). + */ + +#include <stdio.h> + +#include "fcs.h" + +#include "tests.h" + +#include "ms_ca.h" + +#ifdef DMALLOC +#include "dmalloc.h" +#endif + + +#define fcs_is_ss_false_parent(parent, child) \ + (fcs_card_card_num(parent) == fcs_card_card_num(child)+1) + +#define fcs_suit_is_ss_true_parent(parent_suit, child_suit) \ + ((parent_suit) == (child_suit)) + +#define fcs_is_ss_true_parent(parent, child) \ + ( \ + fcs_is_ss_false_parent(parent,child) && \ + (fcs_suit_is_ss_true_parent(fcs_card_suit(parent),fcs_card_suit(child))) \ + ) + +/* + * Those are some macros to make it easier for the programmer. + * */ +#define state_with_locations (*ptr_state_with_locations) +#define state (ptr_state_with_locations->s) +#define new_state_with_locations (*ptr_new_state_with_locations) +#define new_state (ptr_new_state_with_locations->s) + + + +int freecell_solver_sfs_simple_simon_move_sequence_to_founds( + freecell_solver_soft_thread_t * soft_thread, + fcs_state_with_locations_t * ptr_state_with_locations, + int num_freestacks, + int num_freecells, + fcs_derived_states_list_t * derived_states_list, + int reparent + ) +{ + tests_declare_accessors(); + + + fcs_move_t temp_move; + + int check; + + fcs_card_t temp_card; + + /* + * stack - the stack index from which to move cards to the founds. + * cards_num - the number of cards in "stack" + * suit - the suit of the complete sequence + * a - the height of the card + * */ + int stack, cards_num, suit, a; + /* + * card - the current card (at height a) + * above_card - the card above it. + * */ + fcs_card_t card, above_card; + + int state_stacks_num; + tests_define_accessors(); + + state_stacks_num = instance->stacks_num; + + + for(stack=0;stack<state_stacks_num;stack++) + { + cards_num = fcs_stack_len(state, stack); + if (cards_num >= 13) + { + card = fcs_stack_card(state,stack,cards_num-1); + + /* Check if the top 13 cards are a sequence */ + + for(a=2;a<=13;a++) + { + above_card = fcs_stack_card(state,stack,cards_num-a); + if (fcs_is_ss_true_parent(above_card, card)) + { + /* Do nothing - the card is OK for a propert sequence*/ + } + else + { + break; + } + card = above_card; + } + if (a == 14) + { + /* We can move this sequence up there */ + + sfs_check_state_begin(); + + my_copy_stack(stack); + + suit = fcs_card_suit(card); + for(a=0;a<13;a++) + { + fcs_pop_stack_card(new_state, stack, temp_card); + fcs_increment_foundation(new_state, suit); + } + + + fcs_move_init(temp_move); + fcs_move_set_type(temp_move, FCS_MOVE_TYPE_SEQ_TO_FOUNDATION); + fcs_move_set_src_stack(temp_move, stack); + fcs_move_set_foundation(temp_move,suit); + fcs_move_stack_push(moves,temp_move); + + sfs_check_state_end(); + } + } + } + + return FCS_STATE_IS_NOT_SOLVEABLE; +} + +int freecell_solver_sfs_simple_simon_move_sequence_to_true_parent( + freecell_solver_soft_thread_t * soft_thread, + fcs_state_with_locations_t * ptr_state_with_locations, + int num_freestacks, + int num_freecells, + fcs_derived_states_list_t * derived_states_list, + int reparent + ) +{ + tests_declare_accessors(); + + + fcs_move_t temp_move; + + int check; + + /* + * stack - the source stack index on which the sequence currently resides. + * cards_num - the number of cards in "stack". + * suit - the suit of the current card + * a - a temporary variable that designates a card height + * */ + int stack, cards_num, suit, a; + /* + * h - the current height in stack + * */ + int h; + /* + * card - the current card (at height h) + * above_card - the card above it. + * dest_card - the destination card on which to put the sequence + * */ + fcs_card_t card, temp_card, dest_card; + /* + * card_num - the card number (i.e: A, 2 ,3 ... K) of the card, or + * its previous one. + * num_true_seqs - the number of true sequences (i.e: sequences of a + * unified suit) in the source sequence. + * ds - the destination stack index. + * dest_cards_num - the number of cards in "ds". + * */ + int card_num, num_true_seqs, ds, dest_cards_num ; + + int state_stacks_num; + tests_define_accessors(); + + state_stacks_num = instance->stacks_num; + + + for(stack=0;stack<state_stacks_num;stack++) + { + cards_num = fcs_stack_len(state, stack); + if (cards_num > 0) + { + /* Loop on the cards in the stack and try to look for a true + * parent on top one of the stacks */ + card = fcs_stack_card(state,stack,cards_num-1); + card_num = fcs_card_card_num(card); + suit = fcs_card_suit(card); + num_true_seqs = 1; + + for(h=cards_num-2;h>=-1;h--) + { + for(ds=0;ds<state_stacks_num;ds++) + { + if (ds == stack) + { + continue; + } + + dest_cards_num = fcs_stack_len(state,ds); + if (dest_cards_num > 0) + { + dest_card = fcs_stack_card(state, ds, dest_cards_num-1); + if ((fcs_card_suit(dest_card) == suit) && + (fcs_card_card_num(dest_card) == (card_num+1)) + ) + { + /* This is a suitable parent - let's check if we + * have enough empty stacks to make the move feasible */ + if (calc_max_sequence_move(0, num_freestacks) >= num_true_seqs) + { + /* We can do it - so let's move */ + + sfs_check_state_begin(); + + my_copy_stack(stack); + my_copy_stack(ds); + + + fcs_move_sequence(ds, stack, h+1, cards_num-1, a); + sfs_check_state_end(); + + } + } + } + } + + /* Stop if we reached the bottom of the stack */ + if (h == -1) + { + break; + } + + card = fcs_stack_card(state,stack,h); + /* If this is no longer a sequence - move to the next stack */ + if (fcs_card_card_num(card) != card_num+1) + { + break; + } + if (! fcs_suit_is_ss_true_parent(suit, fcs_card_suit(card))) + { + num_true_seqs++; + } + card_num = fcs_card_card_num(card); + suit = fcs_card_suit(card); + } + } + } + + return FCS_STATE_IS_NOT_SOLVEABLE; +} + +int freecell_solver_sfs_simple_simon_move_whole_stack_sequence_to_false_parent( + freecell_solver_soft_thread_t * soft_thread, + fcs_state_with_locations_t * ptr_state_with_locations, + int num_freestacks, + int num_freecells, + fcs_derived_states_list_t * derived_states_list, + int reparent + ) +{ + tests_declare_accessors(); + + + fcs_move_t temp_move; + + int check; + + /* + * stack - the source stack index + * cards_num - number of cards in "stack" + * ds - the dest stack index + * dest_cards_num - number of cards in "ds". + * card - the current card + * card_num - its card number + * suit - its suit + * dest_card - the card at the top of "ds". + * h - the height of the current card on "stack" + * num_true_seqs - the number of true sequences on the current + * false sequence + * */ + int stack, cards_num, suit, a; + fcs_card_t card, temp_card, dest_card; + int card_num, num_true_seqs, h, ds, dest_cards_num ; + + int state_stacks_num; + tests_define_accessors(); + + state_stacks_num = instance->stacks_num; + + for(stack=0;stack<state_stacks_num;stack++) + { + cards_num = fcs_stack_len(state, stack); + if (cards_num > 0) + { + card = fcs_stack_card(state,stack,cards_num-1); + card_num = fcs_card_card_num(card); + suit = fcs_card_suit(card); + num_true_seqs = 1; + + /* Stop if we reached the bottom of the stack */ + for(h=cards_num-2;h>-1;h--) + { + card = fcs_stack_card(state,stack,h); + /* If this is no longer a sequence - move to the next stack */ + if (fcs_card_card_num(card) != card_num+1) + { + break; + } + if (fcs_card_suit(card) != suit) + { + num_true_seqs++; + } + card_num = fcs_card_card_num(card); + suit = fcs_card_suit(card); + } + /* This means that the loop exited prematurely and the stack does + * not contain a sequence. */ + if (h != -1) + { + continue; + } + + for(ds=0;ds<state_stacks_num;ds++) + { + dest_cards_num = fcs_stack_len(state,ds); + if (dest_cards_num > 0) + { + dest_card = fcs_stack_card(state, ds, dest_cards_num-1); + if ( + (fcs_is_ss_false_parent(dest_card, card)) + ) + { + /* This is a suitable parent - let's check if we + * have enough empty stacks to make the move feasible */ + if (calc_max_sequence_move(0, num_freestacks) >= num_true_seqs) + { + /* We can do it - so let's move */ + + sfs_check_state_begin(); + + my_copy_stack(stack); + my_copy_stack(ds); + + + fcs_move_sequence(ds, stack, h+1, cards_num-1, a); + sfs_check_state_end(); + + } + } + } + } + + } + } + + return FCS_STATE_IS_NOT_SOLVEABLE; +} + + +int freecell_solver_sfs_simple_simon_move_sequence_to_true_parent_with_some_cards_above( + freecell_solver_soft_thread_t * soft_thread, + fcs_state_with_locations_t * ptr_state_with_locations, + int num_freestacks, + int num_freecells, + fcs_derived_states_list_t * derived_states_list, + int reparent + ) +{ + tests_declare_accessors(); + + + fcs_move_t temp_move; + int check; + + /* + * stack - the source stack index + * cards_num - the number of cards in "stack" + * h - the height of the current card in "stack" + * card - the card in height "h" + * suit - its suit + * card_num - its card number + * ds - the destionation stack index + * dest_cards_num - the number of cards in "ds" + * dc - the index of the current card in "ds". + * num_separate_false_seqs - this variable tells how many distinct false + * sequences exist above the true parent + * above_num_true_seqs[] - the number of true sequences in each false + * sequence + * seq_points[] - the separation points of the false sequences (i.e: where + * they begin and end) + * stacks_map[] - a boolean map that indicates if one can place a card + * on this stack or is it already taken. + * junk_move_to_stacks[] - the stacks to move each false sequence of the + * junk to. + * false_seq_index - an iterator to hold the index of the current false + * sequence. + * after_junk_num_freestacks - this variable holds the number of stacks + * that remained unoccupied during and after the process of moving + * the junk sequences to different stacks. + * + * */ + int stack, cards_num, suit, a; + fcs_card_t card, temp_card, dest_card; + int card_num, above_num_true_seqs[MAX_NUM_CARDS_IN_A_STACK], h, ds, dest_cards_num ; + int dc; + int seq_points[MAX_NUM_CARDS_IN_A_STACK]; + int num_separate_false_seqs; + int false_seq_index; + int num_true_seqs; + int stacks_map[MAX_NUM_STACKS]; + int after_junk_num_freestacks; + int junk_move_to_stacks[MAX_NUM_STACKS]; + + int state_stacks_num; + tests_define_accessors(); + + state_stacks_num = instance->stacks_num; + + for(stack=0;stack<state_stacks_num;stack++) + { + cards_num = fcs_stack_len(state, stack); + if (cards_num > 0) + { + card = fcs_stack_card(state,stack,cards_num-1); + card_num = fcs_card_card_num(card); + suit = fcs_card_suit(card); + + num_true_seqs = 1; + + + for(h=cards_num-2;h>=-1;h--) + { + for(ds=0;ds<state_stacks_num;ds++) + { + if (ds == stack) + { + continue; + } + + dest_cards_num = fcs_stack_len(state,ds); + if (dest_cards_num > 0) + { + for(dc=dest_cards_num-1;dc>=0;dc--) + { + dest_card = fcs_stack_card(state, ds, dc); + if ((fcs_card_suit(dest_card) == suit) && + (fcs_card_card_num(dest_card) == (card_num+1)) + ) + { + /* This is a suitable parent - let's check if there's a sequence above it. */ + + /* + * above_c - the height of the card that is to be checked. + * above_card - the card at height above_c+1 + * up_above_card - the card at height above_c + * + * */ + int above_c; + fcs_card_t above_card, up_above_card; + + num_separate_false_seqs = 0; + above_card = fcs_stack_card(state, ds, dest_cards_num-1); + above_num_true_seqs[num_separate_false_seqs] = 1; + for(above_c = dest_cards_num-2 ; + above_c > dc ; + above_c-- + ) + { + up_above_card = fcs_stack_card(state, ds, above_c); + if (! fcs_is_ss_false_parent(up_above_card, above_card)) + { + seq_points[num_separate_false_seqs++] = above_c+1; + above_num_true_seqs[num_separate_false_seqs] = 1; + } + above_num_true_seqs[num_separate_false_seqs] += ! (fcs_card_suit(up_above_card) == fcs_card_suit(above_card)); + above_card = up_above_card; + } + + if (dc < dest_cards_num - 1) + { + seq_points[num_separate_false_seqs++] = above_c+1; + } + + for(a=0;a<state_stacks_num;a++) + { + stacks_map[a] = 0; + } + stacks_map[stack] = 1; + stacks_map[ds] = 1; + + after_junk_num_freestacks = num_freestacks; + + for(false_seq_index=0;false_seq_index<num_separate_false_seqs;false_seq_index++) + { + /* Find a suitable place to put it */ + + /* + * clear_junk_dest_stack is the stack to move this particular junk sequence to. + * */ + int clear_junk_dest_stack = -1; + + + /* Let's try to find a suitable parent on top one of the stacks */ + for(clear_junk_dest_stack=0; + clear_junk_dest_stack < state_stacks_num; + clear_junk_dest_stack++ + ) + { + int clear_junk_stack_len; + clear_junk_stack_len = fcs_stack_len(state, clear_junk_dest_stack); + + if ((clear_junk_stack_len > 0) && (stacks_map[clear_junk_dest_stack] == 0)) + { + fcs_card_t clear_junk_dest_card; + + clear_junk_dest_card = fcs_stack_card(state, clear_junk_dest_stack, clear_junk_stack_len-1); + if (fcs_is_ss_false_parent(clear_junk_dest_card, fcs_stack_card(state, ds, seq_points[false_seq_index]))) + { + if (calc_max_sequence_move(0, after_junk_num_freestacks) >= above_num_true_seqs[false_seq_index]) + { + stacks_map[clear_junk_dest_stack] = 1; + break; + } + } + } + } + + if (clear_junk_dest_stack == state_stacks_num) + { + clear_junk_dest_stack = -1; + } + + if (clear_junk_dest_stack == -1) + { + /* Check if there is a vacant stack */ + if (num_freestacks > 0) + { + if (calc_max_sequence_move(0, after_junk_num_freestacks-1) >= above_num_true_seqs[false_seq_index]) + { + /* Find an empty stack and designate it as the destination for the junk */ + for( + clear_junk_dest_stack = 0; + clear_junk_dest_stack < state_stacks_num; + clear_junk_dest_stack++ + ) + { + if ((fcs_stack_len(state, clear_junk_dest_stack) == 0) && (stacks_map[clear_junk_dest_stack] == 0)) + { + stacks_map[clear_junk_dest_stack] = 1; + break; + } + } + } + after_junk_num_freestacks--; + } + } + + if ((clear_junk_dest_stack == -1)) + { + break; + } + junk_move_to_stacks[false_seq_index] = clear_junk_dest_stack; + } + + if (false_seq_index == num_separate_false_seqs) + { + if (calc_max_sequence_move(0, after_junk_num_freestacks) >= num_true_seqs) + { + /* + * We can do it - so let's move everything. + * Notice that we only put the child in a different stack + * then the parent and let it move to the parent in the + * next iteration of the program + * */ + + sfs_check_state_begin(); + + my_copy_stack(ds); + my_copy_stack(stack); + + + /* Move the junk cards to their place */ + + for(false_seq_index=0; + false_seq_index<num_separate_false_seqs; + false_seq_index++ + ) + { + /* + * start and end are the start and end heights of the sequence that is to be moved. + * */ + int start = seq_points[false_seq_index]; + int end = ((false_seq_index == 0) ? (dest_cards_num-1) : (seq_points[false_seq_index-1]-1)); + + my_copy_stack(junk_move_to_stacks[false_seq_index]); + + fcs_move_sequence(junk_move_to_stacks[false_seq_index], ds, start, end, a); + + } + + /* Move the source seq on top of the dest seq */ + fcs_move_sequence(ds, stack, h+1, cards_num-1, a); + + sfs_check_state_end(); + } + } + } + } + } + } + + /* Stop if we reached the bottom of the stack */ + if (h == -1) + { + break; + } + /* If this is no longer a sequence - move to the next stack */ + if (fcs_stack_card_num(state,stack, h) != card_num+1) + { + break; + } + card = fcs_stack_card(state,stack,h); + if (! fcs_suit_is_ss_true_parent(suit, fcs_card_suit(card))) + { + num_true_seqs++; + } + card_num = fcs_card_card_num(card); + suit = fcs_card_suit(card); + } + } + } + + return FCS_STATE_IS_NOT_SOLVEABLE; +} + +int freecell_solver_sfs_simple_simon_move_sequence_with_some_cards_above_to_true_parent( + freecell_solver_soft_thread_t * soft_thread, + fcs_state_with_locations_t * ptr_state_with_locations, + int num_freestacks, + int num_freecells, + fcs_derived_states_list_t * derived_states_list, + int reparent + ) +{ + tests_declare_accessors(); + + + fcs_move_t temp_move; + + int stack, cards_num, suit, a; + fcs_card_t card, temp_card, dest_card; + int card_num, num_true_seqs, ds, dest_cards_num ; + int check; + int sc, num_separate_false_seqs, above_num_true_seqs[MAX_NUM_CARDS_IN_A_STACK]; + int seq_points[MAX_NUM_CARDS_IN_A_STACK]; + int stacks_map[MAX_NUM_STACKS]; + int after_junk_num_freestacks; + int false_seq_index; + int junk_move_to_stacks[MAX_NUM_CARDS_IN_A_STACK]; + + int state_stacks_num; + tests_define_accessors(); + + state_stacks_num = instance->stacks_num; + + for(stack=0;stack<state_stacks_num;stack++) + { + cards_num = fcs_stack_len(state, stack); + if (cards_num > 0) + { + for( sc = cards_num-1 ; sc >= 0 ; sc-- ) + { + int above_c; + fcs_card_t above_card, up_above_card; + int end_of_src_seq; + + card = fcs_stack_card(state, stack, sc); + suit = fcs_card_suit(card); + card_num = fcs_card_card_num(card); + + num_true_seqs = 1; + + for (end_of_src_seq = sc+1; end_of_src_seq < cards_num ; end_of_src_seq++) + { + above_card = fcs_stack_card(state, stack, end_of_src_seq); + if (!fcs_is_ss_false_parent(card, above_card)) + { + break; + } + if (fcs_card_suit(above_card) != fcs_card_suit(card)) + { + num_true_seqs++; + } + card = above_card; + } + + if (end_of_src_seq == cards_num) + { + continue; + } + + /* Split the cards above it into false sequences */ + + num_separate_false_seqs = 0; + above_card = fcs_stack_card(state, stack, cards_num-1); + above_num_true_seqs[num_separate_false_seqs] = 1; + for(above_c = cards_num-2 ; + above_c > end_of_src_seq-1 ; + above_c-- + ) + { + up_above_card = fcs_stack_card(state, stack, above_c); + if (! fcs_is_ss_false_parent(up_above_card, above_card)) + { + seq_points[num_separate_false_seqs++] = above_c+1; + above_num_true_seqs[num_separate_false_seqs] = 1; + } + above_num_true_seqs[num_separate_false_seqs] += ! (fcs_card_suit(up_above_card) == fcs_card_suit(above_card)); + above_card = up_above_card; + } + + if (end_of_src_seq-1 < cards_num-1) + { + seq_points[num_separate_false_seqs++] = above_c+1; + } + + for(ds=0;ds<state_stacks_num;ds++) + { + if (ds == stack) + { + continue; + } + + dest_cards_num = fcs_stack_len(state,ds); + if (dest_cards_num > 0) + { + dest_card = fcs_stack_card(state, ds, dest_cards_num-1); + if ((fcs_card_suit(dest_card) == suit) && + (fcs_card_card_num(dest_card) == (card_num+1)) + ) + { + /* This is a suitable parent - let's check if we + * have enough empty stacks to make the move feasible */ + + for(a=0;a<state_stacks_num;a++) + { + stacks_map[a] = 0; + } + stacks_map[stack] = 1; + stacks_map[ds] = 1; + + after_junk_num_freestacks = num_freestacks; + + for(false_seq_index=0;false_seq_index<num_separate_false_seqs;false_seq_index++) + { + /* Find a suitable place to put it */ + int clear_junk_dest_stack = -1; + + + /* Let's try to find a suitable parent on top one of the stacks */ + for(clear_junk_dest_stack=0; + clear_junk_dest_stack < state_stacks_num; + clear_junk_dest_stack++ + ) + { + int clear_junk_stack_len; + clear_junk_stack_len = fcs_stack_len(state, clear_junk_dest_stack); + + if ((clear_junk_stack_len > 0) && (stacks_map[clear_junk_dest_stack] == 0)) + { + fcs_card_t clear_junk_dest_card; + + clear_junk_dest_card = fcs_stack_card(state, clear_junk_dest_stack, clear_junk_stack_len-1); + if (fcs_is_ss_false_parent(clear_junk_dest_card, fcs_stack_card(state, stack, seq_points[false_seq_index]))) + { + if (calc_max_sequence_move(0, after_junk_num_freestacks) >= above_num_true_seqs[false_seq_index]) + { + stacks_map[clear_junk_dest_stack] = 1; + break; + } + } + } + } + + if (clear_junk_dest_stack == state_stacks_num) + { + clear_junk_dest_stack = -1; + } + + if (clear_junk_dest_stack == -1) + { + /* Check if there is a vacant stack */ + if (num_freestacks > 0) + { + if (calc_max_sequence_move(0, after_junk_num_freestacks-1) >= above_num_true_seqs[false_seq_index]) + { + /* Find an empty stack and designate it as the destination for the junk */ + for( + clear_junk_dest_stack = 0; + clear_junk_dest_stack < state_stacks_num; + clear_junk_dest_stack++ + ) + { + if ((fcs_stack_len(state, clear_junk_dest_stack) == 0) && (stacks_map[clear_junk_dest_stack] == 0)) + { + stacks_map[clear_junk_dest_stack] = 1; + break; + } + } + } + after_junk_num_freestacks--; + } + } + + if ((clear_junk_dest_stack == -1)) + { + break; + } + junk_move_to_stacks[false_seq_index] = clear_junk_dest_stack; + } + + if (false_seq_index == num_separate_false_seqs) + { + if (calc_max_sequence_move(0, after_junk_num_freestacks) > num_true_seqs) + { + sfs_check_state_begin(); + + my_copy_stack(stack); + my_copy_stack(ds); + + + + /* Let's boogie - we can move everything */ + + /* Move the junk cards to their place */ + + for(false_seq_index=0; + false_seq_index<num_separate_false_seqs; + false_seq_index++ + ) + { + int start; + int end; + + int src_stack; + + { + start = seq_points[false_seq_index]; + end = ((false_seq_index == 0) ? (cards_num-1) : (seq_points[false_seq_index-1]-1)); + src_stack = stack; + } + + my_copy_stack(junk_move_to_stacks[false_seq_index]); + + fcs_move_sequence(junk_move_to_stacks[false_seq_index], src_stack, start, end, a); + } + + fcs_move_sequence(ds, stack, sc, end_of_src_seq-1, a); + + sfs_check_state_end(); + } + } + } + } + } + } + } + } + + return FCS_STATE_IS_NOT_SOLVEABLE; +} + +int freecell_solver_sfs_simple_simon_move_sequence_with_junk_seq_above_to_true_parent_with_some_cards_above( + freecell_solver_soft_thread_t * soft_thread, + fcs_state_with_locations_t * ptr_state_with_locations, + int num_freestacks, + int num_freecells, + fcs_derived_states_list_t * derived_states_list, + int reparent + ) +{ + tests_declare_accessors(); + + + fcs_move_t temp_move; + + int check; + + /* + * stack - the source stack index + * cards_num - the number of cards in "stack" + * h - the height of the current card in "stack". + * card - the current card in "stack" + * suit - its suit + * card_num - its card number + * ds - the index of the destination stack + * dest_cards_num - the number of cards in "ds". + * dc - the height of the current card in "ds". + * num_separate_false_seqs - the number of false sequences + * seq_points[] - the places in which the false sequences of the junk begin + * and end + * false_seq_index - an iterator that marks the index of the current + * false sequence + * stacks_map[] - a map of booleans that indicates if one can place a card + * on this stack or is already taken. + * above_num_true_seqs[] - the number of true sequences in each false + * sequence + * num_src_junk_true_seqs - the number of true seqs in the false seq above + * the source card. + * end_of_junk - the height marking the end of the source junk. + * num_true_seqs - the number of true sequences in the false seq which we + * wish to move. + * */ + int stack, cards_num, suit, a; + fcs_card_t card, temp_card, dest_card; + int card_num, above_num_true_seqs[MAX_NUM_CARDS_IN_A_STACK], h, ds, dest_cards_num ; + + int dc; + int seq_points[MAX_NUM_CARDS_IN_A_STACK]; + int num_separate_false_seqs; + int false_seq_index; + int stacks_map[MAX_NUM_STACKS]; + int after_junk_num_freestacks; + int junk_move_to_stacks[MAX_NUM_STACKS]; + int num_src_junk_true_seqs; + int end_of_junk; + int num_true_seqs; + + int state_stacks_num; + tests_define_accessors(); + + state_stacks_num = instance->stacks_num; + + for(stack=0;stack<state_stacks_num;stack++) + { + cards_num = fcs_stack_len(state, stack); + if (cards_num > 0) + { + card = fcs_stack_card(state,stack,cards_num-1); + card_num = fcs_card_card_num(card); + suit = fcs_card_suit(card); + num_src_junk_true_seqs = 1; + + + for(h=cards_num-2;h>=-1;h--) + { + if (h == -1) + { + break; + } + card = fcs_stack_card(state, stack, h); + if (fcs_card_card_num(card) != card_num+1) + { + break; + } + if (fcs_card_suit(card) != suit) + { + num_src_junk_true_seqs++; + } + card_num = fcs_card_card_num(card); + suit = fcs_card_suit(card); + } + + if (h != -1) + { + end_of_junk = h; + num_true_seqs = 1; + + for(;h>=-1;h--) + { + if (h == -1) + { + break; + } + card = fcs_stack_card(state,stack,h); + if (fcs_card_card_num(card) != card_num+1) + { + break; + } + if (fcs_card_suit(card) != suit) + { + num_true_seqs++; + } + card_num = fcs_card_card_num(card); + suit = fcs_card_suit(card); + } + + card_num = fcs_card_card_num(card); + suit = fcs_card_suit(card); + + for(ds=0;ds<state_stacks_num;ds++) + { + if (ds == stack) + { + continue; + } + + dest_cards_num = fcs_stack_len(state,ds); + /* At least a card with another card above it */ + if (dest_cards_num > 1) + { + /* Start at the card below the top one, so we will + * make sure there's at least some junk above it + * */ + for(dc=dest_cards_num-2;dc>=0;dc--) + { + dest_card = fcs_stack_card(state, ds, dc); + if ((fcs_card_suit(dest_card) == suit) && + (fcs_card_card_num(dest_card) == (card_num+1)) + ) + { + /* This is a suitable parent - let's check if there's a sequence above it. */ + int above_c; + fcs_card_t above_card, up_above_card; + + num_separate_false_seqs = 0; + above_card = fcs_stack_card(state, ds, dest_cards_num-1); + above_num_true_seqs[num_separate_false_seqs] = 1; + for(above_c = dest_cards_num-2 ; + above_c > dc ; + above_c-- + ) + { + up_above_card = fcs_stack_card(state, ds, above_c); + if (! fcs_is_ss_false_parent(up_above_card, above_card)) + { + seq_points[num_separate_false_seqs++] = above_c+1; + above_num_true_seqs[num_separate_false_seqs] = 1; + } + above_num_true_seqs[num_separate_false_seqs] += ! (fcs_card_suit(up_above_card) == fcs_card_suit(above_card)); + above_card = up_above_card; + } + + if (dc < dest_cards_num - 1) + { + seq_points[num_separate_false_seqs++] = above_c+1; + } + + for(a=0;a<state_stacks_num;a++) + { + stacks_map[a] = 0; + } + stacks_map[stack] = 1; + stacks_map[ds] = 1; + + after_junk_num_freestacks = num_freestacks; + + for(false_seq_index=0;false_seq_index<num_separate_false_seqs+1;false_seq_index++) + { + /* Find a suitable place to put it */ + int clear_junk_dest_stack = -1; + + fcs_card_t the_card = + ( + (false_seq_index == num_separate_false_seqs) ? + (fcs_stack_card(state, stack, end_of_junk+1)) : + (fcs_stack_card(state, ds, seq_points[false_seq_index])) + ); + + int the_num_true_seqs = + ( + (false_seq_index == num_separate_false_seqs) ? + num_src_junk_true_seqs : + above_num_true_seqs[false_seq_index] + ); + + /* Let's try to find a suitable parent on top one of the stacks */ + for(clear_junk_dest_stack=0; + clear_junk_dest_stack < state_stacks_num; + clear_junk_dest_stack++ + ) + { + int clear_junk_stack_len; + clear_junk_stack_len = fcs_stack_len(state, clear_junk_dest_stack); + + if ((clear_junk_stack_len > 0) && (stacks_map[clear_junk_dest_stack] == 0)) + { + fcs_card_t clear_junk_dest_card; + + clear_junk_dest_card = fcs_stack_card(state, clear_junk_dest_stack, clear_junk_stack_len-1); + if (fcs_is_ss_false_parent(clear_junk_dest_card, the_card)) + { + if (calc_max_sequence_move(0, after_junk_num_freestacks) >= the_num_true_seqs) + { + stacks_map[clear_junk_dest_stack] = 1; + break; + } + } + } + } + + if (clear_junk_dest_stack == state_stacks_num) + { + clear_junk_dest_stack = -1; + } + + if (clear_junk_dest_stack == -1) + { + /* Check if there is a vacant stack */ + if (num_freestacks > 0) + { + if (calc_max_sequence_move(0, after_junk_num_freestacks-1) >= the_num_true_seqs) + { + /* Find an empty stack and designate it as the destination for the junk */ + for( + clear_junk_dest_stack = 0; + clear_junk_dest_stack < state_stacks_num; + clear_junk_dest_stack++ + ) + { + if ((fcs_stack_len(state, clear_junk_dest_stack) == 0) && (stacks_map[clear_junk_dest_stack] == 0)) + { + stacks_map[clear_junk_dest_stack] = 1; + break; + } + } + } + after_junk_num_freestacks--; + } + } + + if ((clear_junk_dest_stack == -1)) + { + break; + } + junk_move_to_stacks[false_seq_index] = clear_junk_dest_stack; + } + + if (false_seq_index == num_separate_false_seqs+1) + { + if (calc_max_sequence_move(0, after_junk_num_freestacks) >= num_true_seqs) + { + /* We can do it - so let's move everything */ + + sfs_check_state_begin(); + + my_copy_stack(stack); + my_copy_stack(ds); + + + /* Move the junk cards to their place */ + + for(false_seq_index=0; + false_seq_index<num_separate_false_seqs+1; + false_seq_index++ + ) + { + int start; + int end; + + int src_stack; + + if (false_seq_index == num_separate_false_seqs) + { + start = end_of_junk+1; + end = cards_num-1; + src_stack = stack; + } + else + { + start = seq_points[false_seq_index]; + end = ((false_seq_index == 0) ? (dest_cards_num-1) : (seq_points[false_seq_index-1]-1)); + src_stack = ds; + } + + my_copy_stack(src_stack); + + my_copy_stack(junk_move_to_stacks[false_seq_index]); + + fcs_move_sequence(junk_move_to_stacks[false_seq_index], src_stack, start, end, a); + } + + /* Move the source seq on top of the dest seq */ + fcs_move_sequence(ds, stack, h, end_of_junk, a); + + sfs_check_state_end(); + } + } + } + } + } + } + } + } + } + + return FCS_STATE_IS_NOT_SOLVEABLE; +} + +int freecell_solver_sfs_simple_simon_move_whole_stack_sequence_to_false_parent_with_some_cards_above( + freecell_solver_soft_thread_t * soft_thread, + fcs_state_with_locations_t * ptr_state_with_locations, + int num_freestacks, + int num_freecells, + fcs_derived_states_list_t * derived_states_list, + int reparent + ) +{ + tests_declare_accessors(); + + + fcs_move_t temp_move; + + int check; + + /* + * stack - the source stack index + * cards_num - the number of cards in "stack" + * h - the height of the current card in stack + * card - the current card + * suit - its suit + * card_num - its card number + * ds - the destination stack index. + * dest_cards_num - the number of cards in it. + * dc - the height of the card in "ds". + * num_separate_false_seqs - this variable tells how many distinct false + * sequences exist above the false parent + * above_num_true_seqs[] - the number of true sequences in each false + * sequence + * seq_points[] - the separation points of the false sequences (i.e: where + * they begin and end) + * stacks_map[] - a boolean map that indicates if one can place a card + * on this stack or is it already taken. + * junk_move_to_stacks[] - the stacks to move each false sequence of the + * junk to. + * false_seq_index - an iterator to hold the index of the current false + * sequence. + * after_junk_num_freestacks - a variable that holds the number of stacks + * that are left unoccupied as part of the junk disposal process. + * + * */ + int stack, cards_num, suit, a; + fcs_card_t card, temp_card, dest_card; + int card_num, num_true_seqs, h, ds, dest_cards_num ; + + int dc, num_separate_false_seqs, above_num_true_seqs[MAX_NUM_CARDS_IN_A_STACK]; + int seq_points[MAX_NUM_CARDS_IN_A_STACK]; + int stacks_map[MAX_NUM_STACKS]; + int after_junk_num_freestacks; + int false_seq_index; + int junk_move_to_stacks[MAX_NUM_STACKS]; + + int state_stacks_num; + tests_define_accessors(); + + state_stacks_num = instance->stacks_num; + + for(stack=0;stack<state_stacks_num;stack++) + { + cards_num = fcs_stack_len(state, stack); + if (cards_num > 0) + { + card = fcs_stack_card(state,stack,cards_num-1); + card_num = fcs_card_card_num(card); + suit = fcs_card_suit(card); + num_true_seqs = 1; + + for(h=cards_num-2;h>=-1;h--) + { + if (h == -1) + { + break; + } + card = fcs_stack_card(state,stack,h); + if (fcs_card_card_num(card) != card_num+1) + { + break; + } + if (fcs_card_suit(card) != suit) + { + num_true_seqs++; + } + card_num = fcs_card_card_num(card); + suit = fcs_card_suit(card); + } + if (h == -1) + { + for(ds=0;ds<state_stacks_num;ds++) + { + dest_cards_num = fcs_stack_len(state,ds); + if (dest_cards_num > 0) + { + for(dc=dest_cards_num-1;dc>=0;dc--) + { + dest_card = fcs_stack_card(state, ds, dc); + if ( + (fcs_card_card_num(dest_card) == (card_num+1)) + ) + { + /* This is a suitable parent - let's check if there's a sequence above it. */ + int above_c; + fcs_card_t above_card, up_above_card; + + num_separate_false_seqs = 0; + above_card = fcs_stack_card(state, ds, dest_cards_num-1); + above_num_true_seqs[num_separate_false_seqs] = 1; + for(above_c = dest_cards_num-2 ; + above_c > dc ; + above_c-- + ) + { + up_above_card = fcs_stack_card(state, ds, above_c); + if (! fcs_is_ss_false_parent(up_above_card, above_card)) + { + seq_points[num_separate_false_seqs++] = above_c+1; + above_num_true_seqs[num_separate_false_seqs] = 1; + } + above_num_true_seqs[num_separate_false_seqs] += ! (fcs_card_suit(up_above_card) == fcs_card_suit(above_card)); + above_card = up_above_card; + } + + if (dc < dest_cards_num - 1) + { + seq_points[num_separate_false_seqs++] = above_c+1; + } + + for(a=0;a<state_stacks_num;a++) + { + stacks_map[a] = 0; + } + stacks_map[stack] = 1; + stacks_map[ds] = 1; + + after_junk_num_freestacks = num_freestacks; + + for(false_seq_index=0;false_seq_index<num_separate_false_seqs;false_seq_index++) + { + /* Find a suitable place to put it */ + int clear_junk_dest_stack = -1; + + fcs_card_t the_card = + (fcs_stack_card(state, ds, seq_points[false_seq_index])) + ; + + + int the_num_true_seqs = + above_num_true_seqs[false_seq_index]; + + + /* Let's try to find a suitable parent on top one of the stacks */ + for(clear_junk_dest_stack=0; + clear_junk_dest_stack < state_stacks_num; + clear_junk_dest_stack++ + ) + { + int clear_junk_stack_len; + clear_junk_stack_len = fcs_stack_len(state, clear_junk_dest_stack); + + if ((clear_junk_stack_len > 0) && (stacks_map[clear_junk_dest_stack] == 0)) + { + fcs_card_t clear_junk_dest_card; + + clear_junk_dest_card = fcs_stack_card(state, clear_junk_dest_stack, clear_junk_stack_len-1); + if (fcs_is_ss_false_parent(clear_junk_dest_card, the_card)) + { + if (calc_max_sequence_move(0, after_junk_num_freestacks) >= the_num_true_seqs) + { + stacks_map[clear_junk_dest_stack] = 1; + break; + } + } + } + } + + if (clear_junk_dest_stack == state_stacks_num) + { + clear_junk_dest_stack = -1; + } + + if ((clear_junk_dest_stack == -1)) + { + break; + } + junk_move_to_stacks[false_seq_index] = clear_junk_dest_stack; + } + + if (false_seq_index == num_separate_false_seqs) + { + /* This is a suitable parent - let's check if we + * have enough empty stacks to make the move feasible */ + if (calc_max_sequence_move(0, num_freestacks) >= num_true_seqs) + { + /* We can do it - so let's move */ + + sfs_check_state_begin(); + + my_copy_stack(stack); + my_copy_stack(ds); + + + /* Move the junk cards to their place */ + + for(false_seq_index=0; + false_seq_index<num_separate_false_seqs; + false_seq_index++ + ) + { + int start; + int end; + + int src_stack; + + { + start = seq_points[false_seq_index]; + end = ((false_seq_index == 0) ? (dest_cards_num-1) : (seq_points[false_seq_index-1]-1)); + src_stack = ds; + } + + my_copy_stack(src_stack); + my_copy_stack(junk_move_to_stacks[false_seq_index]); + + fcs_move_sequence( junk_move_to_stacks[false_seq_index], src_stack, start, end, a); + } + + fcs_move_sequence( ds, stack, h+1, cards_num-1, a); + + sfs_check_state_end(); + + } + } + } + } + } + } + } + } + } + + return FCS_STATE_IS_NOT_SOLVEABLE; +} + +int freecell_solver_sfs_simple_simon_move_sequence_to_parent_on_the_same_stack( + freecell_solver_soft_thread_t * soft_thread, + fcs_state_with_locations_t * ptr_state_with_locations, + int num_freestacks, + int num_freecells, + fcs_derived_states_list_t * derived_states_list, + int reparent + ) +{ + tests_declare_accessors(); + + + fcs_move_t temp_move; + + int check; + + int stack, cards_num, pc, cc; + fcs_card_t parent_card, child_card; + int a; + int after_junk_num_freestacks; + int false_seq_index; + int child_seq_index; + + fcs_card_t temp_card; + + int state_stacks_num; + tests_define_accessors(); + + state_stacks_num = instance->stacks_num; + + for(stack=0 ; stack < state_stacks_num ; stack++) + { + cards_num = fcs_stack_len(state, stack); + if (cards_num > 2) + { + /* Search for a parent card */ + for(pc=0; pc < cards_num-1 ; pc++) + { + parent_card = fcs_stack_card(state, stack, pc); + if ( + fcs_is_ss_true_parent( + parent_card, + fcs_stack_card(state, stack, pc+1) + ) + ) + { + continue; + } + + + for(cc = pc + 2 ; cc < cards_num ; cc++) + { + child_card = fcs_stack_card(state, stack, cc); + if (fcs_is_ss_true_parent( + parent_card, + child_card + ) + ) + { + /* We have a matching parent and child cards */ +#if 0 + printf("Stack %i, Parent %i, Child %i\n", stack, pc, cc); + fflush(stdout); +#endif + + /* + * Now let's try to find stacks to place the cards above + * the child card. + * */ + + int above_num_true_seqs[MAX_NUM_CARDS_IN_A_STACK]; + int seq_points[MAX_NUM_CARDS_IN_A_STACK]; + int stacks_map[MAX_NUM_STACKS]; + int junk_move_to_stacks[MAX_NUM_STACKS]; + int num_separate_false_seqs; + + fcs_card_t above_card, up_above_card; + int above_c; + + int end_of_child_seq; + int child_num_true_seqs; + + end_of_child_seq = cc; + child_num_true_seqs = 1; + while ((end_of_child_seq+1 < cards_num) && + fcs_is_ss_false_parent( + fcs_stack_card(state, stack, end_of_child_seq), + fcs_stack_card(state, stack, end_of_child_seq+1) + ) + ) + { + child_num_true_seqs += (!fcs_is_ss_true_parent( + fcs_stack_card(state, stack, end_of_child_seq), + fcs_stack_card(state, stack, end_of_child_seq+1) + )); + end_of_child_seq++; + } + + num_separate_false_seqs = 0; + above_card = fcs_stack_card(state, stack, cards_num-1); + above_num_true_seqs[num_separate_false_seqs] = 1; + for(above_c = cards_num-2; + above_c > end_of_child_seq ; + above_c-- + ) + { + up_above_card = fcs_stack_card(state, stack, above_c); + if (! fcs_is_ss_false_parent(up_above_card, above_card)) + { + seq_points[num_separate_false_seqs++] = above_c+1; + above_num_true_seqs[num_separate_false_seqs] = 1; + } + above_num_true_seqs[num_separate_false_seqs] += ! (fcs_card_suit(up_above_card) == fcs_card_suit(above_card)); + above_card = up_above_card; + } + + if (end_of_child_seq < cards_num - 1) + { + seq_points[num_separate_false_seqs++] = above_c+1; + } + + /* Add the child to the seq_points */ + child_seq_index = num_separate_false_seqs; + above_num_true_seqs[num_separate_false_seqs] = child_num_true_seqs; + seq_points[num_separate_false_seqs++] = cc; + + /* Add the cards between the parent and the child to the seq_points */ + + above_card = fcs_stack_card(state, stack, cc-1); + above_num_true_seqs[num_separate_false_seqs] = 1; + for(above_c = cc-2; + above_c > pc ; + above_c-- + ) + { + up_above_card = fcs_stack_card(state, stack, above_c); + if (! fcs_is_ss_false_parent(up_above_card, above_card)) + { + seq_points[num_separate_false_seqs++] = above_c+1; + above_num_true_seqs[num_separate_false_seqs] = 1; + } + above_num_true_seqs[num_separate_false_seqs] += ! (fcs_card_suit(up_above_card) == fcs_card_suit(above_card)); + above_card = up_above_card; + } + + if (pc < cc - 1) + { + seq_points[num_separate_false_seqs++] = above_c+1; + } + + + + for(a = 0 ; a < state_stacks_num ; a++) + { + stacks_map[a] = 0; + } + stacks_map[stack] = 1; + + after_junk_num_freestacks = num_freestacks; + + for(false_seq_index=0;false_seq_index<num_separate_false_seqs;false_seq_index++) + { + /* Find a suitable place to put it */ + int clear_junk_dest_stack = -1; + + + /* Let's try to find a suitable parent on top one of the stacks */ + for(clear_junk_dest_stack=0; + clear_junk_dest_stack < state_stacks_num; + clear_junk_dest_stack++ + ) + { + int clear_junk_stack_len; + clear_junk_stack_len = fcs_stack_len(state, clear_junk_dest_stack); + + if ((clear_junk_stack_len > 0) && (stacks_map[clear_junk_dest_stack] == 0)) + { + fcs_card_t clear_junk_dest_card; + + clear_junk_dest_card = fcs_stack_card(state, clear_junk_dest_stack, clear_junk_stack_len-1); + if (fcs_is_ss_false_parent(clear_junk_dest_card, fcs_stack_card(state, stack, seq_points[false_seq_index]))) + { + if (calc_max_sequence_move(0, after_junk_num_freestacks) >= above_num_true_seqs[false_seq_index]) + { + stacks_map[clear_junk_dest_stack] = 1; + break; + } + } + } + } + + if (clear_junk_dest_stack == state_stacks_num) + { + clear_junk_dest_stack = -1; + } + + if (clear_junk_dest_stack == -1) + { + /* Check if there is a vacant stack */ + if (num_freestacks > 0) + { + if (calc_max_sequence_move(0, after_junk_num_freestacks-1) >= above_num_true_seqs[false_seq_index]) + { + /* Find an empty stack and designate it as the destination for the junk */ + for( + clear_junk_dest_stack = 0; + clear_junk_dest_stack < state_stacks_num; + clear_junk_dest_stack++ + ) + { + if ((fcs_stack_len(state, clear_junk_dest_stack) == 0) && (stacks_map[clear_junk_dest_stack] == 0)) + { + stacks_map[clear_junk_dest_stack] = 1; + break; + } + } + } + after_junk_num_freestacks--; + } + } + + if ((clear_junk_dest_stack == -1)) + { + break; + } + junk_move_to_stacks[false_seq_index] = clear_junk_dest_stack; + } + + if (false_seq_index == num_separate_false_seqs) + { + /* Let's check if we can move the child after we are done moving all the junk cards */ + if (calc_max_sequence_move(0, after_junk_num_freestacks) >= child_num_true_seqs) + { + /* We can do it - so let's move everything */ + + sfs_check_state_begin(); + + /* Move the junk cards to their place */ + + my_copy_stack(stack); + + for(false_seq_index=0; + false_seq_index<num_separate_false_seqs; + false_seq_index++ + ) + { + int start = seq_points[false_seq_index]; + int end = ((false_seq_index == 0) ? (cards_num-1) : (seq_points[false_seq_index-1]-1)); + + my_copy_stack(junk_move_to_stacks[false_seq_index]); + + fcs_move_sequence ( junk_move_to_stacks[false_seq_index], stack, start, end, a); + } + + { + int end = fcs_stack_len(new_state, junk_move_to_stacks[child_seq_index])-1; + int start = end-(end_of_child_seq-cc); + + my_copy_stack(junk_move_to_stacks[child_seq_index]); + + + fcs_move_sequence( stack, junk_move_to_stacks[child_seq_index], start, end, a); + } + + sfs_check_state_end(); + } + } + } + } + } + } + } + + return FCS_STATE_IS_NOT_SOLVEABLE; +} + +#undef state_with_locations +#undef state +#undef new_state_with_locations +#undef new_state + |