fcs_state_with_locations_t freecell_solver_initial_user_state_to_c( const char * string, int freecells_num, int stacks_num, int decks_num #ifdef FCS_WITH_TALONS ,int talon_type #endif #ifdef INDIRECT_STACK_STATES , char * indirect_stacks_buffer #endif ) { fcs_state_with_locations_t ret_with_locations; int s,c; const char * str; fcs_card_t card; int first_line; int prefix_found; const char * const * prefixes; int i; int decks_index[4]; fcs_state_init( &ret_with_locations, stacks_num #ifdef INDIRECT_STACK_STATES , indirect_stacks_buffer #endif ); str = string; first_line = 1; #define ret (ret_with_locations.s) #ifdef FCS_WITH_TALONS if (talon_type == FCS_TALON_KLONDIKE) { fcs_klondike_talon_num_redeals_left(ret) = -1; } #endif for(s=0;s<stacks_num;s++) { /* Move to the next stack */ if (!first_line) { while((*str) != '\n') { str++; } str++; } first_line = 0; prefixes = freecells_prefixes; prefix_found = 0; for(i=0;prefixes[i][0] != '\0'; i++) { if (!strncasecmp(str, prefixes[i], strlen(prefixes[i]))) { prefix_found = 1; str += strlen(prefixes[i]); break; } } if (prefix_found) { for(c=0;c<freecells_num;c++) { fcs_empty_freecell(ret, c); } for(c=0;c<freecells_num;c++) { if (c!=0) { while( ((*str) != ' ') && ((*str) != '\t') && ((*str) != '\n') && ((*str) != '\r') ) { str++; } if ((*str == '\n') || (*str == '\r')) { break; } str++; } while ((*str == ' ') || (*str == '\t')) { str++; } if ((*str == '\r') || (*str == '\n')) break; if ((*str == '*') || (*str == '-')) { card = fcs_empty_card; } else { card = fcs_card_user2perl(str); } fcs_put_card_in_freecell(ret, c, card); } while ((*str != '\n') && (*str != '\0')) { str++; } s--; continue; } prefixes = foundations_prefixes; prefix_found = 0; for(i=0;prefixes[i][0] != '\0'; i++) { if (!strncasecmp(str, prefixes[i], strlen(prefixes[i]))) { prefix_found = 1; str += strlen(prefixes[i]); break; } } if (prefix_found) { int d; for(d=0;d<decks_num*4;d++) { fcs_set_foundation(ret, d, 0); } for(d=0;d<4;d++) { decks_index[d] = 0; } while (1) { while((*str == ' ') || (*str == '\t')) str++; if ((*str == '\n') || (*str == '\r')) break; d = fcs_u2p_suit(str); str++; while (*str == '-') str++; c = fcs_u2p_card_number(str); while ( (*str != ' ') && (*str != '\t') && (*str != '\n') && (*str != '\r') ) { str++; } fcs_set_foundation(ret, (decks_index[d]*4+d), c); decks_index[d]++; if (decks_index[d] >= decks_num) { decks_index[d] = 0; } } s--; continue; } #ifdef FCS_WITH_TALONS prefixes = talon_prefixes; prefix_found = 0; for(i=0;prefixes[i][0] != '\0'; i++) { if (!strncasecmp(str, prefixes[i], strlen(prefixes[i]))) { prefix_found = 1; str += strlen(prefixes[i]); break; } } if (prefix_found) { /* Input the Talon */ int talon_size; talon_size = MAX_NUM_DECKS*52+16; ret.talon = malloc(sizeof(fcs_card_t)*talon_size); fcs_talon_pos(ret) = 0; for(c=0 ; c < talon_size ; c++) { /* Move to the next card */ if (c!=0) { while( ((*str) != ' ') && ((*str) != '\t') && ((*str) != '\n') && ((*str) != '\r') ) { str++; } if ((*str == '\n') || (*str == '\r')) { break; } } while ((*str == ' ') || (*str == '\t')) { str++; } if ((*str == '\n') || (*str == '\r')) { break; } card = fcs_card_user2perl(str); fcs_put_card_in_talon(ret, c+(talon_type==FCS_TALON_KLONDIKE), card); } fcs_talon_len(ret) = c; if (talon_type == FCS_TALON_KLONDIKE) { int talon_len; talon_len = fcs_talon_len(ret); fcs_klondike_talon_len(ret) = talon_len; fcs_klondike_talon_stack_pos(ret) = -1; fcs_klondike_talon_queue_pos(ret) = 0; } s--; continue; } prefixes = num_redeals_prefixes; prefix_found = 0; for(i=0;prefixes[i][0] != '\0'; i++) { if (!strncasecmp(str, prefixes[i], strlen(prefixes[i]))) { prefix_found = 1; str += strlen(prefixes[i]); break; } } if (prefix_found) { while ((*str < '0') && (*str > '9') && (*str != '\n')) { str++; } if (*str != '\n') { int num_redeals; num_redeals = atoi(str); if (talon_type == FCS_TALON_KLONDIKE) { fcs_klondike_talon_num_redeals_left(ret) = (num_redeals < 0) ? (-1) : ((num_redeals > 127) ? 127 : num_redeals) ; } } s--; continue; } #endif for(c=0 ; c < MAX_NUM_CARDS_IN_A_STACK ; c++) { /* Move to the next card */ if (c!=0) { while( ((*str) != ' ') && ((*str) != '\t') && ((*str) != '\n') && ((*str) != '\r') ) { str++; } if ((*str == '\n') || (*str == '\r')) { break; } } while ((*str == ' ') || (*str == '\t')) { str++; } if ((*str == '\n') || (*str == '\r')) { break; } card = fcs_card_user2perl(str); fcs_push_card_into_stack(ret, s, card); } } return ret_with_locations; }
/* * 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; } }
/* * This function performs a given move on a state */ void fc_solve_apply_move(fcs_state *const ptr_state_key, fcs_state_locs_struct *const locs, const fcs_internal_move move FREECELLS_AND_STACKS_ARGS()) { fcs_cards_column col; const stack_i src = fcs_int_move_get_src(move); const stack_i dest = fcs_int_move_get_dest(move); #define state_key (ptr_state_key) switch (fcs_int_move_get_type(move)) { case FCS_MOVE_TYPE_STACK_TO_STACK: { fcs_col_transfer_cards(fcs_state_get_col(*state_key, dest), fcs_state_get_col(*state_key, src), fcs_int_move_get_num_cards_in_seq(move)); } break; #if MAX_NUM_FREECELLS > 0 case FCS_MOVE_TYPE_FREECELL_TO_STACK: fcs_state_push(state_key, dest, fcs_freecell_card(*state_key, src)); fcs_empty_freecell(*state_key, src); break; case FCS_MOVE_TYPE_FREECELL_TO_FREECELL: { fcs_card card = fcs_freecell_card(*state_key, src); fcs_put_card_in_freecell(*state_key, dest, card); fcs_empty_freecell(*state_key, src); } break; case FCS_MOVE_TYPE_STACK_TO_FREECELL: { col = fcs_state_get_col(*state_key, src); fcs_card card; fcs_col_pop_card(col, card); fcs_put_card_in_freecell(*state_key, dest, card); } break; #endif case FCS_MOVE_TYPE_STACK_TO_FOUNDATION: col = fcs_state_get_col(*state_key, src); fcs_col_pop_top(col); fcs_increment_foundation(*state_key, dest); break; #if MAX_NUM_FREECELLS > 0 case FCS_MOVE_TYPE_FREECELL_TO_FOUNDATION: fcs_empty_freecell(*state_key, src); fcs_increment_foundation(*state_key, dest); break; #endif #ifndef FCS_FREECELL_ONLY case FCS_MOVE_TYPE_SEQ_TO_FOUNDATION: col = fcs_state_get_col(*state_key, src); for (int i = 0; i < 13; i++) { fcs_col_pop_top(col); fcs_increment_foundation(*state_key, dest); } break; #endif case FCS_MOVE_TYPE_CANONIZE: if (locs) { fc_solve_canonize_state_with_locs(state_key, locs PASS_FREECELLS(freecells_num) PASS_STACKS(stacks_num)); } else { fc_solve_canonize_state(state_key PASS_FREECELLS(freecells_num) PASS_STACKS(stacks_num)); } break; } #undef state_key }