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; }
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; }
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); }
/* * 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); }
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); }