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 void generic_populate_seq_points(
    const fcs_cards_column_t dest_col,
    const int dc,
    sequences_analysis_t * const seqs,
    const int dest_cards_num
)
{
    int num_separate_false_seqs = seqs->num_separate_false_seqs;
    seqs->above_num_true_seqs[num_separate_false_seqs] = 1;
    fcs_card_t above_card = fcs_col_get_card(dest_col, dest_cards_num-1);
    for (int above_c = dest_cards_num-2 ; above_c > dc ; above_c--)
    {
        const fcs_card_t up_above_card = fcs_col_get_card(dest_col, above_c);
        if (! fcs_is_ss_false_parent(up_above_card, above_card))
        {
            seqs->seq_points[num_separate_false_seqs++] = above_c+1;
            seqs->above_num_true_seqs[num_separate_false_seqs] = 1;
        }
        seqs->above_num_true_seqs[num_separate_false_seqs] +=
            ! fcs_is_ss_suit_true(up_above_card, above_card);
        above_card = up_above_card;
    }

    if (dc <= dest_cards_num - 2)
    {
        seqs->seq_points[num_separate_false_seqs++] = dc+1;
    }

    seqs->num_separate_false_seqs = num_separate_false_seqs;
}
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;
}
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
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.º 7
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;
}
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.º 9
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);
}