/*
 * 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_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

