Exemplo n.º 1
0
static GCC_INLINE int update_col_cards_under_sequences(
        fc_solve_soft_thread_t * soft_thread,
        fcs_cards_column_t col,
        double * cards_under_sequences_ptr
        )
{
    int cards_num;
    int c;
    fcs_card_t this_card, prev_card;
#ifndef FCS_FREECELL_ONLY
    int sequences_are_built_by = 
        GET_INSTANCE_SEQUENCES_ARE_BUILT_BY(soft_thread->hard_thread->instance)
        ;
#endif

    cards_num = fcs_col_len(col);
    c = cards_num - 2;
    this_card = fcs_col_get_card(col, c+1);
    prev_card = fcs_col_get_card(col, c);
    while ((c >= 0) && fcs_is_parent_card(this_card,prev_card))
    {
        this_card = prev_card;
        if (--c>=0)
        {
            prev_card = fcs_col_get_card(col, c);
        }
    }
    *cards_under_sequences_ptr += pow(c+1, FCS_A_STAR_CARDS_UNDER_SEQUENCES_EXPONENT);
    return c;
}
static GCC_INLINE const int get_seq_h(const fcs_const_cards_column_t col, int * const num_true_seqs_out_ptr)
{
    const int cards_num = fcs_col_len(col);

    fcs_card_t card = fcs_col_get_card(col,cards_num-1);
    int num_true_seqs = 1;

    int h;
    /* Stop if we reached the bottom of the stack */
    for ( h=cards_num-2 ; h>-1 ; h--)
    {
        const fcs_card_t next_card = fcs_col_get_card(col, h);
        /* If this is no longer a sequence - move to the next stack */
        if (!fcs_is_ss_false_parent(next_card, card))
        {
            break;
        }

        if (!fcs_is_ss_suit_true(next_card, card))
        {
            num_true_seqs++;
        }

        card = next_card;
    }

    *num_true_seqs_out_ptr = num_true_seqs;

    return h+1;
}
static char * get_the_positions_by_rank_data__ss_generator(
    fc_solve_soft_thread_t * const soft_thread,
    const fcs_state_t * const the_state
)
{
    fc_solve_instance_t * const instance = HT_INSTANCE(soft_thread->hard_thread);
    SET_GAME_PARAMS();

#define FCS_SS_POS_BY_RANK_WIDTH (13+1)
#define FCS_POS_BY_RANK_LEN ( FCS_SS_POS_BY_RANK_WIDTH * 4 )
#define FCS_POS_BY_RANK_SIZE (sizeof(positions_by_rank[0]) * FCS_POS_BY_RANK_LEN)
#define FCS_POS_IDX(rank, suit) ( (suit)*FCS_SS_POS_BY_RANK_WIDTH + (rank) )

    pos_by_rank_t * const positions_by_rank = SMALLOC(positions_by_rank, FCS_POS_BY_RANK_LEN);

    memset(positions_by_rank, -1, FCS_POS_BY_RANK_SIZE);
    for (int ds = 0 ; ds < LOCAL_STACKS_NUM ; ds++)
    {
        const fcs_const_cards_column_t dest_col = fcs_state_get_col(*the_state, ds);
        const int dest_cards_num = fcs_col_len(dest_col);

        for (int dc = 0 ; dc < dest_cards_num ; dc++)
        {
            const fcs_card_t card = fcs_col_get_card(dest_col, dc);
            const int suit = fcs_card_suit(card);
            const int rank = fcs_card_rank(card);

            const pos_by_rank_t pos = {.col = ds, .height = dc};
            positions_by_rank[FCS_POS_IDX(rank, suit)] = pos;
        }
    }

    return (char *)positions_by_rank;
}
static GCC_INLINE void populate_seq_points(
    const fcs_cards_column_t dest_col,
    const int dc,
    sequences_analysis_t * const seqs
)
{
    seqs->num_separate_false_seqs = 0;
    generic_populate_seq_points(dest_col, dc, seqs, fcs_col_len(dest_col));
}
Exemplo n.º 5
0
static void initialize_a_star_rater(
    fc_solve_soft_thread_t * soft_thread,
    fcs_state_extra_info_t * ptr_state_val
    )
{
#ifndef HARD_CODED_NUM_STACKS
    fc_solve_hard_thread_t * hard_thread = soft_thread->hard_thread;
    fc_solve_instance_t * instance = hard_thread->instance;
#endif
    fcs_state_t * ptr_state_key = ptr_state_val->key;

    int a, c, cards_num;
    fcs_card_t this_card, prev_card;
    double cards_under_sequences;
    fcs_cards_column_t col;
#ifndef FCS_FREECELL_ONLY
    int sequences_are_built_by = instance->sequences_are_built_by;
#endif

    cards_under_sequences = 0;
    for(a=0;a<INSTANCE_STACKS_NUM;a++)
    {
        col = fcs_state_get_col(*ptr_state_key, a);
        cards_num = fcs_col_len(col);
        if (cards_num <= 1)
        {
            continue;
        }

        c = cards_num-2;
        this_card = fcs_col_get_card(col, c+1);
        prev_card = fcs_col_get_card(col, c);
        while (fcs_is_parent_card(this_card,prev_card) && (c >= 0))
        {
            c--;
            this_card = prev_card;
            if (c>=0)
            {
                prev_card = fcs_col_get_card(col, c);
            }
        }
        cards_under_sequences += pow(c+1, FCS_A_STAR_CARDS_UNDER_SEQUENCES_EXPONENT);
    }
    soft_thread->a_star_initial_cards_under_sequences = cards_under_sequences;
}
Exemplo n.º 6
0
int fc_solve_a_star_or_bfs_do_solve(
    fc_solve_soft_thread_t * soft_thread
    )
{
    fc_solve_hard_thread_t * hard_thread = soft_thread->hard_thread;
    fc_solve_instance_t * instance = hard_thread->instance;

    fcs_state_t * ptr_state_key;
    fcs_state_extra_info_t * ptr_state_val, * ptr_new_state_val;
    int num_vacant_stacks, num_vacant_freecells;
    fcs_states_linked_list_item_t * save_item;
    int a;
    int check;
    fcs_derived_states_list_t derived;
    int derived_index;

    int method;
#ifndef HARD_CODED_NUM_FREECELLS
    int freecells_num;
#endif
#ifndef HARD_CODED_NUM_STACKS
    int stacks_num;
#endif
    int tests_order_num;
    int * tests_order_tests;
    int calc_real_depth = instance->calc_real_depth;
    int soft_thread_id = soft_thread->id;
    int is_a_complete_scan = soft_thread->is_a_complete_scan;

    int scans_synergy = instance->scans_synergy;
    fcs_states_linked_list_item_t * bfs_queue = soft_thread->bfs_queue;
    PQUEUE * a_star_pqueue = soft_thread->a_star_pqueue;
    fcs_states_linked_list_item_t * bfs_queue_last_item = soft_thread->bfs_queue_last_item;

    derived.num_states = 0;
    derived.states = NULL;

    tests_order_num = soft_thread->tests_order.num;
    tests_order_tests = soft_thread->tests_order.tests;

    ptr_state_val = soft_thread->first_state_to_check_val;

    method = soft_thread->method;
#ifndef HARD_CODED_NUM_FREECELLS
    freecells_num = instance->freecells_num;
#endif

#ifndef HARD_CODED_NUM_STACKS
    stacks_num = instance->stacks_num;
#endif

    /* Continue as long as there are states in the queue or
       priority queue. */
    while ( ptr_state_val != NULL)
    {
         TRACE0("Start of loop");        /*
         * If this is an optimization scan and the state being checked is not
         * in the original solution path - move on to the next state
         * */
        if ((method == FCS_METHOD_OPTIMIZE) && (!(ptr_state_val->visited & FCS_VISITED_IN_SOLUTION_PATH)))
        {
            goto label_next_state;
        }

        /*
         * It the state has already been visited - move on to the next
         * state.
         * */
        if ((method == FCS_METHOD_OPTIMIZE) ?
                (ptr_state_val->visited & FCS_VISITED_IN_OPTIMIZED_PATH) :
                ((ptr_state_val->visited & FCS_VISITED_DEAD_END) ||
                 (is_scan_visited(ptr_state_val, soft_thread_id)))
                )
        {
            goto label_next_state;
        }
        TRACE0("Counting cells");

        ptr_state_key = ptr_state_val->key;
        /* Count the free-cells */
        num_vacant_freecells = 0;
        for(a=0;a<LOCAL_FREECELLS_NUM;a++)
        {
            if (fcs_freecell_card_num((*ptr_state_key), a) == 0)
            {
                num_vacant_freecells++;
            }
        }

        /* Count the number of unoccupied stacks */

        num_vacant_stacks = 0;
        for(a=0;a<LOCAL_STACKS_NUM;a++)
        {
            if (fcs_col_len(fcs_state_get_col(the_state, a)) == 0)
            {
                num_vacant_stacks++;
            }
        }


        if (check_if_limits_exceeded())
        {
            soft_thread->first_state_to_check_val = ptr_state_val;

            TRACE0("myreturn - FCS_STATE_SUSPEND_PROCESS");
            myreturn(FCS_STATE_SUSPEND_PROCESS);
        }

        TRACE0("debug_iter_output");
        if (instance->debug_iter_output)
        {
#ifdef DEBUG
            printf("ST Name: %s\n", soft_thread->name);
#endif
            instance->debug_iter_output_func(
                    (void*)instance->debug_iter_output_context,
                    instance->num_times,
                    ptr_state_val->depth,
                    (void*)instance,
                    ptr_state_val,
                    ((ptr_state_val->parent_val == NULL) ?
                        0 :
                        ptr_state_val->parent_val->visited_iter
                    )
                    );
        }


        if ((num_vacant_stacks == LOCAL_STACKS_NUM) && (num_vacant_freecells == LOCAL_FREECELLS_NUM))
        {
            instance->final_state_val = ptr_state_val;

            myreturn(FCS_STATE_WAS_SOLVED);
        }

        calculate_real_depth(
            ptr_state_val
        );

        soft_thread->num_vacant_freecells = num_vacant_freecells;
        soft_thread->num_vacant_stacks = num_vacant_stacks;

        if (soft_thread->a_star_positions_by_rank)
        {
            free(soft_thread->a_star_positions_by_rank);
            soft_thread->a_star_positions_by_rank = NULL;
        }

        TRACE0("perform_tests");
        /* Do all the tests at one go, because that the way it should be
           done for BFS and A*
        */
        derived.num_states = 0;
        for(a=0 ;
            a < tests_order_num;
            a++)
        {
            check = fc_solve_sfs_tests[tests_order_tests[a] & FCS_TEST_ORDER_NO_FLAGS_MASK] (
                    soft_thread,
                    ptr_state_val,
                    &derived
                    );
            if ((check == FCS_STATE_BEGIN_SUSPEND_PROCESS) ||
                (check == FCS_STATE_EXCEEDS_MAX_NUM_TIMES) ||
                (check == FCS_STATE_SUSPEND_PROCESS))
            {
                /* Save the current position in the scan */
                soft_thread->first_state_to_check_val = ptr_state_val;

                myreturn(FCS_STATE_SUSPEND_PROCESS);
            }
        }

        if (is_a_complete_scan)
        {
            ptr_state_val->visited |= FCS_VISITED_ALL_TESTS_DONE;
        }

        /* Increase the number of iterations by one .
         * */
        {
            instance->num_times++;
            hard_thread->num_times++;
        }

        TRACE0("Insert all states");
        /* Insert all the derived states into the PQ or Queue */

        for(derived_index = 0 ; derived_index < derived.num_states ; derived_index++)
        {
            ptr_new_state_val = derived.states[derived_index].state_ptr;

            if (method == FCS_METHOD_A_STAR)
            {
                fc_solve_PQueuePush(
                    a_star_pqueue,
                    ptr_new_state_val,
                    fc_solve_a_star_rate_state(soft_thread,
                        ptr_new_state_val
                        )
                    );
            }
            else
            {
                fc_solve_bfs_enqueue_state(
                    soft_thread,
                    ptr_new_state_val
                    );
            }
        }

        if (method == FCS_METHOD_OPTIMIZE)
        {
            ptr_state_val->visited |= FCS_VISITED_IN_OPTIMIZED_PATH;
        }
        else
        {
            set_scan_visited(
                    ptr_state_val,
                    soft_thread_id
                    );

            if (derived.num_states == 0)
            {
                if (is_a_complete_scan)
                {
                    mark_as_dead_end(
                            ptr_state_val
                            );
                }
            }
        }

        ptr_state_val->visited_iter = instance->num_times-1;

label_next_state:
        TRACE0("Label next state");
        /*
            Extract the next item in the queue/priority queue.
        */
        if ((method == FCS_METHOD_BFS) || (method == FCS_METHOD_OPTIMIZE))
        {
            save_item = bfs_queue->next;
            if (save_item != bfs_queue_last_item)
            {
                ptr_state_val = save_item->s;
                bfs_queue->next = save_item->next;
                free(save_item);
            }
            else
            {
                ptr_state_val = NULL;
            }
        }
        else
        {
            /* It is an A* scan */
            fc_solve_PQueuePop(a_star_pqueue,
                &ptr_state_val
                );
        }
    }

    myreturn(FCS_STATE_IS_NOT_SOLVEABLE);
}
Exemplo n.º 7
0
static pq_rating_t fc_solve_a_star_rate_state(
    fc_solve_soft_thread_t * soft_thread,
    fcs_state_extra_info_t * ptr_state_val
    )
{
    fc_solve_hard_thread_t * hard_thread = soft_thread->hard_thread;
    fc_solve_instance_t * instance = hard_thread->instance;
    fcs_state_t * ptr_state_key = ptr_state_val->key;

    double ret=0;
    int a, c, cards_num, num_cards_in_founds;
    int num_vacant_stacks, num_vacant_freecells;
    fcs_card_t this_card, prev_card;
    double cards_under_sequences, temp;
    double seqs_over_renegade_cards;
    fcs_cards_column_t col;
#ifndef FCS_FREECELL_ONLY
    int sequences_are_built_by = instance->sequences_are_built_by;
#endif
#ifndef HARD_CODED_NUM_FREECELLS
    int freecells_num = instance->freecells_num;
#endif
#ifndef HARD_CODED_NUM_STACKS
    int stacks_num = instance->stacks_num;
#endif
    double * a_star_weights = soft_thread->a_star_weights;
#ifndef FCS_FREECELL_ONLY
    int unlimited_sequence_move = instance->unlimited_sequence_move;
#else
    #define unlimited_sequence_move 0
#endif
#ifndef HARD_CODED_NUM_DECKS
    int decks_num = instance->decks_num;
#endif

    cards_under_sequences = 0;
    num_vacant_stacks = 0;
    seqs_over_renegade_cards = 0;
    for(a=0;a<LOCAL_STACKS_NUM;a++)
    {
        col = fcs_state_get_col(*(ptr_state_key), a);
        cards_num = fcs_col_len(col);

        if (cards_num == 0)
        {
            num_vacant_stacks++;
        }

        if (cards_num <= 1)
        {
            continue;
        }

        c = cards_num-2;
        this_card = fcs_col_get_card(col, c+1);
        prev_card = fcs_col_get_card(col, c);
        while ((c >= 0) && fcs_is_parent_card(this_card,prev_card))
        {
            c--;
            this_card = prev_card;
            if (c>=0)
            {
                prev_card = fcs_col_get_card(col, c);
            }
        }
        cards_under_sequences += pow(c+1, FCS_A_STAR_CARDS_UNDER_SEQUENCES_EXPONENT);
        if (c >= 0)
        {
            seqs_over_renegade_cards +=
                ((unlimited_sequence_move) ?
                    1 :
                    pow(cards_num-c-1, FCS_A_STAR_SEQS_OVER_RENEGADE_CARDS_EXPONENT)
                    );
        }
    }

    ret += ((soft_thread->a_star_initial_cards_under_sequences - cards_under_sequences)
            / soft_thread->a_star_initial_cards_under_sequences) * a_star_weights[FCS_A_STAR_WEIGHT_CARDS_UNDER_SEQUENCES];

    ret += (seqs_over_renegade_cards /
               pow(LOCAL_DECKS_NUM*52, FCS_A_STAR_SEQS_OVER_RENEGADE_CARDS_EXPONENT) )
           * a_star_weights[FCS_A_STAR_WEIGHT_SEQS_OVER_RENEGADE_CARDS];

    num_cards_in_founds = 0;
    for(a=0;a<(LOCAL_DECKS_NUM<<2);a++)
    {
        num_cards_in_founds += fcs_foundation_value((*ptr_state_key), a);
    }

    ret += ((double)num_cards_in_founds/(LOCAL_DECKS_NUM*52)) * a_star_weights[FCS_A_STAR_WEIGHT_CARDS_OUT];

    num_vacant_freecells = 0;
    for(a=0;a<LOCAL_FREECELLS_NUM;a++)
    {
        if (fcs_freecell_card_num((*ptr_state_key),a) == 0)
        {
            num_vacant_freecells++;
        }
    }

    if (instance->empty_stacks_fill == FCS_ES_FILLED_BY_ANY_CARD)
    {
        if (unlimited_sequence_move)
        {
            temp = (((double)num_vacant_freecells+num_vacant_stacks)/(LOCAL_FREECELLS_NUM+INSTANCE_STACKS_NUM));
        }
        else
        {
            temp = (((double)((num_vacant_freecells+1)<<num_vacant_stacks)) / ((LOCAL_FREECELLS_NUM+1)<<(INSTANCE_STACKS_NUM)));
        }
    }
    else
    {
        if (unlimited_sequence_move)
        {
            temp = (((double)num_vacant_freecells)/LOCAL_FREECELLS_NUM);
        }
        else
        {
            temp = 0;
        }
    }

    ret += (temp * a_star_weights[FCS_A_STAR_WEIGHT_MAX_SEQUENCE_MOVE]);

    if (ptr_state_val->depth <= 20000)
    {
        ret += ((20000 - ptr_state_val->depth)/20000.0) * a_star_weights[FCS_A_STAR_WEIGHT_DEPTH];
    }

    TRACE0("Before return");

    return (int)(ret*INT_MAX);
}
Exemplo n.º 8
0
int fc_solve_soft_dfs_do_solve(
    fc_solve_soft_thread_t * soft_thread,
    int to_randomize
    )
{
    fc_solve_hard_thread_t * hard_thread = soft_thread->hard_thread;
    fc_solve_instance_t * instance = hard_thread->instance;

    fcs_state_t * ptr_state_key;
    fcs_state_extra_info_t * ptr_state_val;
    int check;
    int do_first_iteration;
    fcs_soft_dfs_stack_item_t * the_soft_dfs_info;
#ifndef HARD_CODED_NUM_FREECELLS
    int freecells_num;
#endif
#ifndef HARD_CODED_NUM_STACKS
    int stacks_num;
#endif
    int dfs_max_depth;

    int tests_order_num = soft_thread->tests_order.num;
    int * tests_order_tests = soft_thread->tests_order.tests;
    int calc_real_depth = instance->calc_real_depth;
    int is_a_complete_scan = soft_thread->is_a_complete_scan;
    int soft_thread_id = soft_thread->id;
    fcs_derived_states_list_t * derived_states_list;
    int scans_synergy;

#ifndef HARD_CODED_NUM_FREECELLS
    freecells_num = instance->freecells_num;
#endif

#ifndef HARD_CODED_NUM_STACKS
    stacks_num = instance->stacks_num;
#endif
    scans_synergy = instance->scans_synergy;

    the_soft_dfs_info = &(soft_thread->soft_dfs_info[soft_thread->depth]);

    dfs_max_depth = soft_thread->dfs_max_depth;
    ptr_state_val = the_soft_dfs_info->state_val;
    derived_states_list = &(the_soft_dfs_info->derived_states_list);
    
    calculate_real_depth(
        ptr_state_val
    );

    TRACE0("Before depth loop");
    /*
        The main loop.
    */
    while (soft_thread->depth >= 0)
    {
        /*
            Increase the "maximal" depth if it is about to be exceeded.
        */
        if (soft_thread->depth+1 >= dfs_max_depth)
        {
            fc_solve_increase_dfs_max_depth(soft_thread);

            /* Because the address of soft_thread->soft_dfs_info may
             * be changed
             * */
            the_soft_dfs_info = &(soft_thread->soft_dfs_info[soft_thread->depth]);
            dfs_max_depth = soft_thread->dfs_max_depth;
            /* This too has to be re-synced */
            derived_states_list = &(the_soft_dfs_info->derived_states_list);
        }

        TRACE0("Before current_state_index check");
        /* All the resultant states in the last test conducted were covered */
        if (the_soft_dfs_info->current_state_index ==
            derived_states_list->num_states
           )
        {
            if (the_soft_dfs_info->test_index >= tests_order_num)
            {
                /* Backtrack to the previous depth. */

                if (is_a_complete_scan)
                {
                    ptr_state_val->visited |= FCS_VISITED_ALL_TESTS_DONE;
                    mark_as_dead_end(
                        ptr_state_val
                    );
                }

                free(the_soft_dfs_info->positions_by_rank);
                if (--soft_thread->depth < 0)
                {
                    break;
                }
                else
                {
                    the_soft_dfs_info--;
                    derived_states_list = &(the_soft_dfs_info->derived_states_list);
                    ptr_state_val = the_soft_dfs_info->state_val;
                    ptr_state_key = ptr_state_val->key;
                    soft_thread->num_vacant_freecells = the_soft_dfs_info->num_vacant_freecells;
                    soft_thread->num_vacant_stacks = the_soft_dfs_info->num_vacant_stacks;
                }

                continue; /* Just to make sure depth is not -1 now */
            }

            derived_states_list->num_states = 0;

            TRACE0("Before iter_handler");
            /* If this is the first test, then count the number of unoccupied
               freeceels and stacks and check if we are done. */
            if (the_soft_dfs_info->test_index == 0)
            {
                int num_vacant_stacks, num_vacant_freecells;
                int i;

                TRACE0("In iter_handler");

                if (instance->debug_iter_output)
                {
#ifdef DEBUG
                    printf("ST Name: %s\n", soft_thread->name);
#endif
                    instance->debug_iter_output_func(
                        (void*)instance->debug_iter_output_context,
                        instance->num_times,
                        soft_thread->depth,
                        (void*)instance,
                        ptr_state_val,
                        ((soft_thread->depth == 0) ?
                            0 :
                            soft_thread->soft_dfs_info[soft_thread->depth-1].state_val->visited_iter
                        )
                        );
                }

                ptr_state_key = ptr_state_val->key;

                /* Count the free-cells */
                num_vacant_freecells = 0;
                for(i=0;i<LOCAL_FREECELLS_NUM;i++)
                {
                    if (fcs_freecell_card_num(the_state, i) == 0)
                    {
                        num_vacant_freecells++;
                    }
                }

                /* Count the number of unoccupied stacks */

                num_vacant_stacks = 0;
                for(i=0;i<LOCAL_STACKS_NUM;i++)
                {
                    if (fcs_col_len(fcs_state_get_col(the_state, i)) == 0)
                    {
                        num_vacant_stacks++;
                    }
                }

                /* Check if we have reached the empty state */
                if ((num_vacant_stacks == LOCAL_STACKS_NUM) &&
                    (num_vacant_freecells  == LOCAL_FREECELLS_NUM))
                {
                    instance->final_state_val = ptr_state_val;

                    TRACE0("Returning FCS_STATE_WAS_SOLVED");
                    myreturn(FCS_STATE_WAS_SOLVED);
                }
                /*
                    Cache num_vacant_freecells and num_vacant_stacks in their
                    appropriate stacks, so they won't be calculated over and over
                    again.
                  */
                soft_thread->num_vacant_freecells =
                    the_soft_dfs_info->num_vacant_freecells =
                    num_vacant_freecells;
                soft_thread->num_vacant_stacks =
                    the_soft_dfs_info->num_vacant_stacks =
                    num_vacant_stacks;
            }

            TRACE0("After iter_handler");
            /* Always do the first test */
            do_first_iteration = 1;

            while (
                    /* Make sure we do not exceed the number of tests */
                    (the_soft_dfs_info->test_index < tests_order_num) &&
                    (
                        /* Always do the first test */
                        do_first_iteration ||
                        (
                            /* This is a randomized scan. Else - quit after the first iteration */
                            to_randomize &&
                            /* We are still on a random group */
                            (tests_order_tests[ the_soft_dfs_info->test_index ] & FCS_TEST_ORDER_FLAG_RANDOM) &&
                            /* A new random group did not start */
                            (! (tests_order_tests[ the_soft_dfs_info->test_index ] & FCS_TEST_ORDER_FLAG_START_RANDOM_GROUP))
                         )
                    )
                 )
            {
                do_first_iteration = 0;

                check = fc_solve_sfs_tests[tests_order_tests[
                        the_soft_dfs_info->test_index
                    ] & FCS_TEST_ORDER_NO_FLAGS_MASK] (
                        soft_thread,
                        ptr_state_val,
                        derived_states_list
                    );

                if ((check == FCS_STATE_BEGIN_SUSPEND_PROCESS) ||
                    (check == FCS_STATE_EXCEEDS_MAX_NUM_TIMES) ||
                    (check == FCS_STATE_SUSPEND_PROCESS))
                {
                    /* Have this test be re-performed */
                    derived_states_list->num_states = 0;
                    the_soft_dfs_info->current_state_index = 0;
                    TRACE0("Returning FCS_STATE_SUSPEND_PROCESS (after sfs_tests)");
                    myreturn(FCS_STATE_SUSPEND_PROCESS);
                }

                /* Move the counter to the next test */
                the_soft_dfs_info->test_index++;
            }


            {
                int a, j;
                int swap_save;
                int * rand_array, * ra_ptr;
                int num_states = derived_states_list->num_states;

                if (num_states >
                        the_soft_dfs_info->derived_states_random_indexes_max_size)
                {
                    the_soft_dfs_info->derived_states_random_indexes_max_size =
                        num_states;
                    the_soft_dfs_info->derived_states_random_indexes =
                        realloc(
                            the_soft_dfs_info->derived_states_random_indexes,
                            sizeof(the_soft_dfs_info->derived_states_random_indexes[0]) * the_soft_dfs_info->derived_states_random_indexes_max_size
                            );
                }
                rand_array = the_soft_dfs_info->derived_states_random_indexes;

                for(a=0, ra_ptr = rand_array; a < num_states ; a++)
                {
                    *(ra_ptr++) = a;
                }
                /* If we just conducted the tests for a random group -
                 * randomize. Else - keep those indexes as the unity vector.
                 *
                 * Also, do not randomize if this is a pure soft-DFS scan.
                 * */
                if (to_randomize && tests_order_tests[ the_soft_dfs_info->test_index-1 ] & FCS_TEST_ORDER_FLAG_RANDOM)
                {
                    a = num_states-1;
                    while (a > 0)
                    {
                        j =
                            (
                                fc_solve_rand_get_random_number(
                                    soft_thread->rand_gen
                                )
                                % (a+1)
                            );

                        swap_save = rand_array[a];
                        rand_array[a] = rand_array[j];
                        rand_array[j] = swap_save;
                        a--;
                    }
                }
            }

            /* We just performed a test, so the index of the first state that
               ought to be checked in this depth is 0.
               */
            the_soft_dfs_info->current_state_index = 0;
        }

        {
            int num_states = derived_states_list->num_states;
            fcs_derived_states_list_item_t * derived_states =
                derived_states_list->states;
            int * rand_array = the_soft_dfs_info->derived_states_random_indexes;
            fcs_state_extra_info_t * single_derived_state;

            while (the_soft_dfs_info->current_state_index <
                   num_states)
            {
                single_derived_state = derived_states[
                        rand_array[
                            the_soft_dfs_info->current_state_index++
                        ]
                    ].state_ptr;

                if (
                    (! (single_derived_state->visited &
                        FCS_VISITED_DEAD_END)
                    ) &&
                    (! is_scan_visited(
                        single_derived_state,
                        soft_thread_id)
                    )
                   )
                {
                    instance->num_times++;
                    hard_thread->num_times++;

                    set_scan_visited(
                        single_derived_state,
                        soft_thread_id
                    );

                    single_derived_state->visited_iter = instance->num_times;

                    /*
                        I'm using current_state_indexes[depth]-1 because we already
                        increased it by one, so now it refers to the next state.
                    */
                    soft_thread->depth++;
                    the_soft_dfs_info++;

                    the_soft_dfs_info->state_val =
                        ptr_state_val =
                        single_derived_state;

                    the_soft_dfs_info->test_index = 0;
                    the_soft_dfs_info->current_state_index = 0;
                    the_soft_dfs_info->positions_by_rank = NULL;
                    derived_states_list = &(the_soft_dfs_info->derived_states_list);
                    derived_states_list->num_states = 0;

                    calculate_real_depth(
                        ptr_state_val
                    );

                    if (check_if_limits_exceeded())
                    {
                        TRACE0("Returning FCS_STATE_SUSPEND_PROCESS (inside current_state_index)");
                        myreturn(FCS_STATE_SUSPEND_PROCESS);
                    }

                    break;
                }
            }
        }
    }

    /*
     * We need to bump the number of iterations so it will be ready with
     * a fresh iterations number for the next scan that takes place.
     * */
    instance->num_times++;
    hard_thread->num_times++;

    soft_thread->depth = -1;

    return FCS_STATE_IS_NOT_SOLVEABLE;
}
Exemplo n.º 9
0
/*
 * Calculate, cache and return the positions_by_rank meta-data
 * about the currently-evaluated state.
 */
extern char * fc_solve_get_the_positions_by_rank_data(
        fc_solve_soft_thread_t * soft_thread,
        fcs_state_extra_info_t * ptr_state_val
        )
{
    char * * positions_by_rank_location;
    switch(soft_thread->method)
    {
        case FCS_METHOD_SOFT_DFS:
        case FCS_METHOD_RANDOM_DFS:
            {
                positions_by_rank_location = &(
                    soft_thread->soft_dfs_info[
                        soft_thread->depth
                    ].positions_by_rank
                    );
            }
            break;
        default:
            {
                positions_by_rank_location = &(
                        soft_thread->a_star_positions_by_rank
                        );
            }
            break;
    }

    if (! *positions_by_rank_location)
    {
        char * positions_by_rank;
#if (!(defined(HARD_CODED_NUM_FREECELLS) && defined(HARD_CODED_NUM_STACKS) && defined(HARD_CODED_NUM_DECKS)))
        fc_solve_instance_t * instance;
#endif
        fcs_state_t * ptr_state_key;

#ifndef HARD_CODED_NUM_DECKS
        int decks_num;
#endif
#ifndef HARD_CODED_NUM_STACKS
        int stacks_num;
#endif
#ifndef FCS_FREECELL_ONLY
        int sequences_are_built_by;
#endif

        ptr_state_key = ptr_state_val->key;

#if (!(defined(HARD_CODED_NUM_FREECELLS) && defined(HARD_CODED_NUM_STACKS) && defined(HARD_CODED_NUM_DECKS)))
        instance = soft_thread->hard_thread->instance;
#endif

#ifndef HARD_CODED_NUM_DECKS
        decks_num = instance->decks_num;
#endif
#ifndef HARD_CODED_NUM_STACKS
        stacks_num = instance->stacks_num;
#endif
#ifndef FCS_FREECELL_ONLY
        sequences_are_built_by = instance->sequences_are_built_by;
#endif

        /* We don't keep track of kings (rank == 13). */
#define NUM_POS_BY_RANK_SLOTS 13
        /* We need 2 chars per card - one for the column_idx and one
         * for the card_idx.
         *
         * We also need it times 13 for each of the ranks.
         *
         * We need (4*LOCAL_DECKS_NUM+1) slots to hold the cards plus a
         * (-1,-1) (= end) padding.             * */
#define FCS_POS_BY_RANK_SIZE (sizeof(positions_by_rank[0]) * NUM_POS_BY_RANK_SLOTS * FCS_POS_BY_RANK_WIDTH)

        positions_by_rank = malloc(FCS_POS_BY_RANK_SIZE);

        memset(positions_by_rank, -1, FCS_POS_BY_RANK_SIZE);

        {
            char * positions_by_rank_slots[NUM_POS_BY_RANK_SLOTS];

            {
                int c;

                /* Initialize the pointers to the first available slots */
                for ( c=0 ; c < NUM_POS_BY_RANK_SLOTS ; c++ )
                {
                    positions_by_rank_slots[c] = &positions_by_rank[
                        (((LOCAL_DECKS_NUM << 2)+1) << 1) * c
                    ];
                }
            }

            /* Populate positions_by_rank by looping over the stacks and
             * indices looking for the cards and filling them. */

            {
                int ds;

                for(ds=0;ds<LOCAL_STACKS_NUM;ds++)
                {
                    fcs_cards_column_t dest_col;
                    int top_card_idx;
                    fcs_card_t dest_card;

                    dest_col = fcs_state_get_col(*(ptr_state_key), ds);
                    top_card_idx = fcs_col_len(dest_col);

                    if ((top_card_idx--) == 0)
                    {
                        continue;
                    }

                    {
                        fcs_card_t dest_below_card;
                        int dc;
                        for (
                              dc=0,
                              dest_card = fcs_col_get_card(dest_col, 0)
                                ;
                              dc < top_card_idx
                                ;
                              dc++,
                              dest_card = dest_below_card
                            )
                        {
                            dest_below_card = fcs_col_get_card(dest_col, dc+1);
                            if (!fcs_is_parent_card(dest_below_card, dest_card))
                            {
                                *(positions_by_rank_slots[fcs_card_card_num(dest_card)-1]++) = (char)ds;
                                *(positions_by_rank_slots[fcs_card_card_num(dest_card)-1]++) = (char)dc;
                            }
                        }
                    }
                    *(positions_by_rank_slots[fcs_card_card_num(dest_card)-1]++) = (char)ds;
                    *(positions_by_rank_slots[fcs_card_card_num(dest_card)-1]++) = (char)top_card_idx;
                }
            }
        }

        *positions_by_rank_location = positions_by_rank;
    }

    return *positions_by_rank_location;
}
Exemplo n.º 10
0
/*
 * This function performs a given move on a state
 */
void fc_solve_apply_move(
        fcs_state_extra_info_t * state_val,
        fcs_internal_move_t move,
        int freecells_num,
        int stacks_num,
        int decks_num GCC_UNUSED
        )
{
    fcs_card_t card;
    fcs_cards_column_t col;

    fcs_state_t * state_key = state_val->key;

    switch(fcs_int_move_get_type(move))
    {
        case FCS_MOVE_TYPE_STACK_TO_STACK:
        {
            fcs_cards_column_t dest_col;
            int i;

            col = fcs_state_get_col(*state_key, fcs_int_move_get_src_stack(move));
            dest_col = fcs_state_get_col(*state_key, fcs_int_move_get_dest_stack(move));
            for(i=0 ; i<fcs_int_move_get_num_cards_in_seq(move) ; i++)
            {
                fcs_col_push_col_card(
                    dest_col,
                    col, 
                    fcs_col_len(col) - fcs_int_move_get_num_cards_in_seq(move)+i
                );
            }
            for(i=0 ; i<fcs_int_move_get_num_cards_in_seq(move) ; i++)
            {
                fcs_col_pop_top(col);
            }
        }
        break;
        case FCS_MOVE_TYPE_FREECELL_TO_STACK:
        {
            col = fcs_state_get_col(*state_key, fcs_int_move_get_dest_stack(move));
            fcs_col_push_card(col, fcs_freecell_card(*state_key, fcs_int_move_get_src_freecell(move)));
            fcs_empty_freecell(*state_key, fcs_int_move_get_src_freecell(move));
        }
        break;
        case FCS_MOVE_TYPE_FREECELL_TO_FREECELL:
        {
            card = fcs_freecell_card(*state_key, fcs_int_move_get_src_freecell(move));
            fcs_put_card_in_freecell(*state_key, fcs_int_move_get_dest_freecell(move), card);
            fcs_empty_freecell(*state_key, fcs_int_move_get_src_freecell(move));
        }
        break;

        case FCS_MOVE_TYPE_STACK_TO_FREECELL:
        {
            col = fcs_state_get_col(*state_key, fcs_int_move_get_src_stack(move));
            fcs_col_pop_card(col, card);
            fcs_put_card_in_freecell(*state_key, fcs_int_move_get_dest_freecell(move), card);
        }
        break;

        case FCS_MOVE_TYPE_STACK_TO_FOUNDATION:
        {
            col = fcs_state_get_col(
                *state_key, 
                fcs_int_move_get_src_stack(move)
                );
            fcs_col_pop_top(col);
            fcs_increment_foundation(*state_key, fcs_int_move_get_foundation(move));
        }
        break;

        case FCS_MOVE_TYPE_FREECELL_TO_FOUNDATION:
        {
            fcs_empty_freecell(*state_key, fcs_int_move_get_src_freecell(move));
            fcs_increment_foundation(*state_key, fcs_int_move_get_foundation(move));
        }
        break;

        case FCS_MOVE_TYPE_SEQ_TO_FOUNDATION:
        {
            int i;

            col = fcs_state_get_col(*state_key, fcs_int_move_get_src_stack(move));
            for (i=0 ; i<13 ; i++)
            {
                fcs_col_pop_top(col);
                fcs_increment_foundation(*state_key, fcs_int_move_get_foundation(move));
            }
        }
        break;

#ifndef FCS_WITHOUT_CARD_FLIPPING
        case FCS_MOVE_TYPE_FLIP_CARD:
        {
            col = fcs_state_get_col(*state_key, fcs_int_move_get_src_stack(move));
            fcs_col_flip_card(col, fcs_col_len(col)-1);
        }
        break;
#endif

        case FCS_MOVE_TYPE_CANONIZE:
        {
            fc_solve_canonize_state(
                state_val,
                freecells_num, stacks_num
            );
        }
        break;

    }
}
Exemplo n.º 11
0
char * fc_solve_move_to_string_w_state(
        fcs_state_extra_info_t * state_val,
        int freecells_num GCC_UNUSED, 
        int stacks_num GCC_UNUSED,
        int decks_num GCC_UNUSED,
        fcs_move_t move,
        int standard_notation
        )
{
    char string[256];

    fcs_state_t * state_key = state_val->key;

    switch(fcs_move_get_type(move))
    {
        case FCS_MOVE_TYPE_STACK_TO_STACK:
            if ((standard_notation == STANDARD_NOTATION_EXTENDED) &&
                /* More than one card was moved */
                (fcs_move_get_num_cards_in_seq(move) > 1) &&
                /* It was a move to an empty stack */
                (fcs_col_len(fcs_state_get_col(*state_key, fcs_move_get_dest_stack(move))) ==
                 fcs_move_get_num_cards_in_seq(move))
               )
            {
                sprintf(string, "%i%iv%x",
                    1+fcs_move_get_src_stack(move),
                    1+fcs_move_get_dest_stack(move),
                    fcs_move_get_num_cards_in_seq(move)
                   );
            }
            else if (standard_notation)
            {
                sprintf(string, "%i%i",
                    1+fcs_move_get_src_stack(move),
                    1+fcs_move_get_dest_stack(move)
                    );
            }
            else
            {
                sprintf(string, "Move %i cards from stack %i to stack %i",
                    fcs_move_get_num_cards_in_seq(move),
                    fcs_move_get_src_stack(move),
                    fcs_move_get_dest_stack(move)
                );
            }
        break;

        case FCS_MOVE_TYPE_FREECELL_TO_STACK:
            if (standard_notation)
            {
                sprintf(string, "%c%i",
                    ('a'+convert_freecell_num(fcs_move_get_src_freecell(move))),
                    1+fcs_move_get_dest_stack(move)
                    );
            }
            else
            {
                sprintf(string, "Move a card from freecell %i to stack %i",
                    fcs_move_get_src_freecell(move),
                    fcs_move_get_dest_stack(move)
                    );
            }

        break;

        case FCS_MOVE_TYPE_FREECELL_TO_FREECELL:
            if (standard_notation)
            {
                register char src_c = (char)('a'+(char)convert_freecell_num(fcs_move_get_src_freecell(move)));
                register char dest_c = (char)('a'+(char)convert_freecell_num(fcs_move_get_dest_freecell(move)));

                sprintf(string, "%c%c", src_c, dest_c);
            }
            else
            {
                sprintf(string, "Move a card from freecell %i to freecell %i",
                    fcs_move_get_src_freecell(move),
                    fcs_move_get_dest_freecell(move)
                    );
            }

        break;

        case FCS_MOVE_TYPE_STACK_TO_FREECELL:
            if (standard_notation)
            {
                sprintf(string, "%i%c",
                    1+fcs_move_get_src_stack(move),
                    ('a'+convert_freecell_num(fcs_move_get_dest_freecell(move)))
                    );
            }
            else
            {
                sprintf(string, "Move a card from stack %i to freecell %i",
                    fcs_move_get_src_stack(move),
                    fcs_move_get_dest_freecell(move)
                    );
            }

        break;

        case FCS_MOVE_TYPE_STACK_TO_FOUNDATION:
            if (standard_notation)
            {
                sprintf(string, "%ih", 1+fcs_move_get_src_stack(move));
            }
            else
            {
                sprintf(string, "Move a card from stack %i to the foundations",
                    fcs_move_get_src_stack(move)
                    );
            }

        break;


        case FCS_MOVE_TYPE_FREECELL_TO_FOUNDATION:
            if (standard_notation)
            {
                sprintf(string, "%ch", ('a'+convert_freecell_num(fcs_move_get_src_freecell(move))));
            }
            else
            {
                sprintf(string,
                    "Move a card from freecell %i to the foundations",
                    fcs_move_get_src_freecell(move)
                    );
            }

        break;

        case FCS_MOVE_TYPE_SEQ_TO_FOUNDATION:
            if (standard_notation)
            {
                sprintf(string, "%ih", fcs_move_get_src_stack(move));
            }
            else
            {
                sprintf(string,
                    "Move the sequence on top of Stack %i to the foundations",
                    fcs_move_get_src_stack(move)
                    );
            }
        break;

        default:
            string[0] = '\0';
        break;
    }

    return strdup(string);
}
Exemplo n.º 12
0
static void GCC_INLINE fc_solve_cache_stacks(
        fc_solve_hard_thread_t * hard_thread,
        fcs_state_t * new_state_key,
        fcs_state_extra_info_t * new_state_val
        )
{
    int a;
#if (FCS_STACK_STORAGE == FCS_STACK_STORAGE_INTERNAL_HASH)
#ifdef FCS_ENABLE_SECONDARY_HASH_VALUE
    SFO_hash_value_t hash_value_int;
#endif
#elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_JUDY)
    PWord_t * PValue;
#endif
    void * cached_stack;
    char * new_ptr;
    fc_solve_instance_t * instance = hard_thread->instance;
#ifndef HARD_CODED_NUM_STACKS
    int stacks_num = instance->stacks_num;
#endif
    fcs_cards_column_t column;
    register int col_len;

    for(a=0 ; a < LOCAL_STACKS_NUM ; a++)
    {
        /*
         * If the stack is not a copy - it is already cached so skip
         * to the next stack
         * */
        if (! (new_state_val->stacks_copy_on_write_flags & (1 << a)))
        {
            continue;
        }
        /* new_state_key->stacks[a] = realloc(new_state_key->stacks[a], fcs_stack_len(new_state_key, a)+1); */

        column = fcs_state_get_col(*new_state_key, a);
        col_len = (fcs_col_len(column)+1);

        fcs_compact_alloc_typed_ptr_into_var(new_ptr, char, hard_thread->stacks_allocator, col_len);
        memcpy(new_ptr, column, col_len);
        new_state_key->stacks[a] = new_ptr;

#if FCS_STACK_STORAGE == FCS_STACK_STORAGE_INTERNAL_HASH
#ifdef FCS_ENABLE_SECONDARY_HASH_VALUE
        /* Calculate the hash value for the stack */
        /* This hash function was ripped from the Perl source code.
         * (It is not derived work however). */
        {
            const char * s_ptr = (char*)(new_state_key->stacks[a]);
            const char * s_end = s_ptr+fcs_stack_len(*new_state_key, a)+1;
            hash_value_int = 0;
            while (s_ptr < s_end)
            {
                hash_value_int += (hash_value_int << 5) + *(s_ptr++);
            }
            hash_value_int += (hash_value_int >> 5);
        }

        if (hash_value_int < 0)
        {
            /*
             * This is a bit mask that nullifies the sign bit of the
             * number so it will always be positive
             * */
            hash_value_int &= (~(1<<((sizeof(hash_value_int)<<3)-1)));
        }
#endif

        {
            void * dummy;
            int verdict;

            column = fcs_state_get_col(*new_state_key, a);

            verdict = fc_solve_hash_insert(
                instance->stacks_hash,
                column,
                column,
                &cached_stack,
                &dummy,
                perl_hash_function(
                    (ub1 *)new_state_key->stacks[a],
                    col_len
                    )
#ifdef FCS_ENABLE_SECONDARY_HASH_VALUE
                , hash_value_int
#endif
                );

            replace_with_cached(verdict);
        }

#elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_AVL_TREE) || (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_REDBLACK_TREE)

#if (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_AVL_TREE)
#define LIBAVL_INSERT(x,y) avl_insert(x,y)
#elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBAVL_REDBLACK_TREE)
#define LIBAVL_INSERT(x,y) rb_insert(x,y)
#else
#error unknown FCS_STACK_STORAGE
#endif

        cached_stack =
            LIBAVL_INSERT(
            instance->stacks_tree,
            new_state_key->stacks[a]
            );

#undef LIBAVL_INSERT

        replace_with_cached(cached_stack != NULL);

#elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_LIBREDBLACK_TREE)
        cached_stack = (void *)rbsearch(
            new_state_key->stacks[a],
            instance->stacks_tree
            );

        replace_with_cached(cached_stack != new_state_key->stacks[a]);
#elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GLIB_TREE)
        cached_stack = g_tree_lookup(
             instance->stacks_tree,
             (gpointer)new_state_key->stacks[a]
             );

        /* replace_with_cached contains an if statement */
        replace_with_cached(cached_stack != NULL)
        else
        {
            g_tree_insert(
                instance->stacks_tree,
                (gpointer)new_state_key->stacks[a],
                (gpointer)new_state_key->stacks[a]
                );
        }
#elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_GLIB_HASH)
        cached_stack = g_hash_table_lookup(
            instance->stacks_hash,
            (gconstpointer)new_state_key->stacks[a]
            );
        replace_with_cached(cached_stack != NULL)
        else
        {
            g_hash_table_insert(
                instance->stacks_hash,
                (gpointer)new_state_key->stacks[a],
                (gpointer)new_state_key->stacks[a]
                );
        }
#elif (FCS_STACK_STORAGE == FCS_STACK_STORAGE_JUDY)
        JHSI(
            PValue,
            instance->stacks_judy_array,
            new_state_key->stacks[a],
            (fcs_stack_len(*new_state_key, a)+1)
        );
        /* TODO : Handle out-of-memory. */
        if (*PValue == 0)
        {
            /*  A new stack */
            *PValue = (PWord_t)new_state_key->stacks[a];
        }
        else
        {
            cached_stack = (void *)(*PValue);
            replace_with_cached(1);
        }
#else
#error FCS_STACK_STORAGE is not set to a good value.
#endif
    }
}
Exemplo n.º 13
0
static GCC_INLINE pq_rating_t fc_solve_a_star_rate_state(
    fc_solve_soft_thread_t * soft_thread,
    fcs_state_extra_info_t * ptr_state_val
    )
{
#ifndef FCS_FREECELL_ONLY
    fc_solve_hard_thread_t * hard_thread = soft_thread->hard_thread;
    fc_solve_instance_t * instance = hard_thread->instance;
#endif
    fcs_state_t * ptr_state_key = ptr_state_val->key;

    double ret=0;
    int a, c, cards_num, num_cards_in_founds;
    int num_vacant_stacks, num_vacant_freecells;
    double cards_under_sequences, temp;
    double seqs_over_renegade_cards;
    fcs_cards_column_t col;
#ifndef HARD_CODED_NUM_FREECELLS
    int freecells_num = INSTANCE_FREECELLS_NUM;
#endif
#ifndef HARD_CODED_NUM_STACKS
    int stacks_num = INSTANCE_STACKS_NUM;
#endif
#define my_a_star_weights soft_thread->method_specific.befs.meth.befs.a_star_weights
    double * a_star_weights = my_a_star_weights;
#ifndef FCS_FREECELL_ONLY
    int unlimited_sequence_move = INSTANCE_UNLIMITED_SEQUENCE_MOVE;
#else
    #define unlimited_sequence_move 0
#endif
#ifndef HARD_CODED_NUM_DECKS
    int decks_num = INSTANCE_DECKS_NUM;
#endif

    cards_under_sequences = 0;
    num_vacant_stacks = 0;
    seqs_over_renegade_cards = 0;
    for(a=0;a<LOCAL_STACKS_NUM;a++)
    {
        col = fcs_state_get_col(*(ptr_state_key), a);
        cards_num = fcs_col_len(col);

        if (cards_num == 0)
        {
            num_vacant_stacks++;
        }

        if (cards_num <= 1)
        {
            continue;
        }

        c = update_col_cards_under_sequences(soft_thread, col, &cards_under_sequences);
        if (c >= 0)
        {
            seqs_over_renegade_cards +=
                ((unlimited_sequence_move) ?
                    1 :
                    FCS_SEQS_OVER_RENEGADE_POWER(cards_num-c-1)
                    );
        }
    }

    ret += ((soft_thread->method_specific.befs.meth.befs.a_star_initial_cards_under_sequences - cards_under_sequences)
            / soft_thread->method_specific.befs.meth.befs.a_star_initial_cards_under_sequences) * a_star_weights[FCS_A_STAR_WEIGHT_CARDS_UNDER_SEQUENCES];

    ret += (seqs_over_renegade_cards /
               FCS_SEQS_OVER_RENEGADE_POWER(LOCAL_DECKS_NUM*(13*4))
            )
           * a_star_weights[FCS_A_STAR_WEIGHT_SEQS_OVER_RENEGADE_CARDS];

    num_cards_in_founds = 0;
    for(a=0;a<(LOCAL_DECKS_NUM<<2);a++)
    {
        num_cards_in_founds += fcs_foundation_value((*ptr_state_key), a);
    }

    ret += ((double)num_cards_in_founds/(LOCAL_DECKS_NUM*52)) * a_star_weights[FCS_A_STAR_WEIGHT_CARDS_OUT];

    num_vacant_freecells = 0;
    for(a=0;a<LOCAL_FREECELLS_NUM;a++)
    {
        if (fcs_freecell_card_num((*ptr_state_key),a) == 0)
        {
            num_vacant_freecells++;
        }
    }

#ifdef FCS_FREECELL_ONLY
#define is_filled_by_any_card() 1
#else
#define is_filled_by_any_card() (INSTANCE_EMPTY_STACKS_FILL == FCS_ES_FILLED_BY_ANY_CARD)
#endif
    if (is_filled_by_any_card())
    {
        if (unlimited_sequence_move)
        {
            temp = (((double)num_vacant_freecells+num_vacant_stacks)/(LOCAL_FREECELLS_NUM+INSTANCE_STACKS_NUM));
        }
        else
        {
            temp = (((double)((num_vacant_freecells+1)<<num_vacant_stacks)) / ((LOCAL_FREECELLS_NUM+1)<<(INSTANCE_STACKS_NUM)));
        }
    }
    else
    {
        if (unlimited_sequence_move)
        {
            temp = (((double)num_vacant_freecells)/LOCAL_FREECELLS_NUM);
        }
        else
        {
            temp = 0;
        }
    }

    ret += (temp * a_star_weights[FCS_A_STAR_WEIGHT_MAX_SEQUENCE_MOVE]);

    if (ptr_state_val->depth <= 20000)
    {
        ret += ((20000 - ptr_state_val->depth)/20000.0) * a_star_weights[FCS_A_STAR_WEIGHT_DEPTH];
    }

    TRACE0("Before return");

    return (int)(ret*INT_MAX);
}
static GCC_INLINE const fcs_bool_t generic_false_seq_index_loop(
    const int stacks_num,
    fcs_kv_state_t * const raw_ptr_state_raw,
    const int num_vacant_stacks,
    const fcs_cards_column_t col,
    sequences_analysis_t * const seqs,
    const int stack_idx,
    const int ds,
    const fcs_bool_t behavior_flag,
    const fcs_bool_t should_src_col,
    const fcs_card_t src_card,
    const int num_src_junk_true_seqs
    )
{
    const int num_separate_false_seqs = seqs->num_separate_false_seqs;
    fcs_bool_t stacks_map[STACKS_MAP_LEN];
    init_stacks_map(stacks_map, stack_idx, ds);

    int after_junk_num_freestacks = num_vacant_stacks;

    const int false_seq_index_limit
        = num_separate_false_seqs + (should_src_col ? 1 : 0);

    int false_seq_index;

    for (false_seq_index = 0 ;
        false_seq_index < false_seq_index_limit ;
        false_seq_index++)
    {
        const fcs_bool_t is_ultimate_iter =
            (false_seq_index == num_separate_false_seqs);

        /* Find a suitable place to put it */
        const fcs_card_t the_card =
            is_ultimate_iter
            ? src_card
            : fcs_col_get_card(col, seqs->seq_points[false_seq_index]);

        const int the_num_true_seqs =
            is_ultimate_iter
            ? num_src_junk_true_seqs
            : seqs->above_num_true_seqs[false_seq_index];

        /* Let's try to find a suitable parent on top one of the stacks */
        int clear_junk_dest_stack;
        for(clear_junk_dest_stack=0;
            clear_junk_dest_stack < stacks_num;
            clear_junk_dest_stack++
        )
        {
            const fcs_const_cards_column_t clear_junk_dest_col = fcs_state_get_col(state, clear_junk_dest_stack);
            const int clear_junk_stack_len = fcs_col_len(clear_junk_dest_col);

            if (! ((clear_junk_stack_len > 0) && (! stacks_map[clear_junk_dest_stack])))
            {
                continue;
            }

            if (
                fcs_is_ss_false_parent(
                    fcs_col_get_card(
                        clear_junk_dest_col,
                        clear_junk_stack_len-1
                    ),
                    the_card
                )
            )
            {
                if (calc_max_simple_simon_seq_move(after_junk_num_freestacks) >= the_num_true_seqs)
                {
                    stacks_map[clear_junk_dest_stack] = TRUE;
                    break;
                }
            }
        }

        if (clear_junk_dest_stack == stacks_num)
        {
            /* Check if there is a vacant stack */
            if (behavior_flag || (!
                (
                    (num_vacant_stacks > 0)
                    &&
                    (calc_max_simple_simon_seq_move(after_junk_num_freestacks-1) >= the_num_true_seqs)
                )
            ))
            {
                break;
            }
            /* Find an empty stack and designate it as the destination for the junk */
            for(
                clear_junk_dest_stack = 0;
                clear_junk_dest_stack < stacks_num;
                clear_junk_dest_stack++
            )
            {
                if ((fcs_col_len(fcs_state_get_col(state, clear_junk_dest_stack)) == 0) && (! stacks_map[clear_junk_dest_stack]))
                {
                    stacks_map[clear_junk_dest_stack] = TRUE;
                    break;
                }
            }
            after_junk_num_freestacks--;
        }

        seqs->junk_move_to_stacks[false_seq_index] = clear_junk_dest_stack;
    }

    seqs->after_junk_num_freestacks = after_junk_num_freestacks;
    return (false_seq_index == false_seq_index_limit);
}
Exemplo n.º 15
0
static inline bool generic_false_seq_index_loop(const int stacks_num,
    fcs_kv_state raw_state_raw, const int num_vacant_stacks,
    const fcs_cards_column col, sequences_analysis *const seqs,
    const stack_i stack_idx, const int ds, const bool behavior_flag,
    const bool should_src_col, const fcs_card src_card,
    const size_t num_src_junk_true_seqs)
{
    const size_t num_separate_false_seqs = seqs->num_separate_false_seqs;
    bool stacks_map[STACKS_MAP_LEN];
    init_stacks_map(stacks_map, stack_idx, ds);

    int after_junk_num_freestacks = num_vacant_stacks;

    const size_t false_seq_index_limit =
        num_separate_false_seqs + (should_src_col ? 1 : 0);

    size_t false_seq_idx;

    for (false_seq_idx = 0; false_seq_idx < false_seq_index_limit;
         false_seq_idx++)
    {
        const bool is_ultimate_iter =
            (false_seq_idx == num_separate_false_seqs);

        /* Find a suitable place to put it */
        const fcs_card the_card =
            is_ultimate_iter
                ? src_card
                : fcs_col_get_card(col, seqs->seq_points[false_seq_idx]);

        const size_t the_num_true_seqs =
            is_ultimate_iter ? num_src_junk_true_seqs
                             : seqs->above_num_true_seqs[false_seq_idx];

        /* Let's try to find a suitable parent on top one of the stacks */
        int clear_junk_dest_stack;
        for (clear_junk_dest_stack = 0; clear_junk_dest_stack < stacks_num;
             ++clear_junk_dest_stack)
        {
            const fcs_const_cards_column clear_junk_dest_col =
                fcs_state_get_col(state, clear_junk_dest_stack);
            const int clear_junk_stack_len = fcs_col_len(clear_junk_dest_col);

            if (!((clear_junk_stack_len > 0) &&
                    (!stacks_map[clear_junk_dest_stack])))
            {
                continue;
            }

            if (fcs_is_ss_false_parent(fcs_col_get_card(clear_junk_dest_col,
                                           clear_junk_stack_len - 1),
                    the_card))
            {
                if (calc_max_simple_simon_seq_move(after_junk_num_freestacks) >=
                    the_num_true_seqs)
                {
                    goto found;
                }
            }
        }

        /* Check if there is a vacant stack */
        if (behavior_flag ||
            (!((num_vacant_stacks > 0) &&
                (calc_max_simple_simon_seq_move(
                     after_junk_num_freestacks - 1) >= the_num_true_seqs))))
        {
            break;
        }
        --after_junk_num_freestacks;
        /* Find an empty stack and designate it as the destination for the
         * junk */
        for (clear_junk_dest_stack = 0;; ++clear_junk_dest_stack)
        {
            if (fcs_state_col_is_empty(state, clear_junk_dest_stack) &&
                (!stacks_map[clear_junk_dest_stack]))
            {
                break;
            }
        }

    found:
        stacks_map[clear_junk_dest_stack] = true;
        seqs->junk_move_to_stacks[false_seq_idx] =
            (size_t)clear_junk_dest_stack;
    }

    seqs->after_junk_num_freestacks = after_junk_num_freestacks;
    return (false_seq_idx == false_seq_index_limit);
}