You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1717 lines
70 KiB
1717 lines
70 KiB
15 years ago
|
/*
|
||
|
* 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
|
||
|
|