You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegames/kpat/freecell-solver/lib.c

1245 lines
28 KiB

/*
* lib.c - library interface functions of Freecell Solver.
*
* Written by Shlomi Fish (shlomif@vipe.technion.ac.il), 2000
*
* This file is in the public domain (it's uncopyrighted).
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "card.h"
#include "fcs.h"
#include "preset.h"
#include "fcs_user.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif
struct fcs_instance_item_struct
{
freecell_solver_instance_t * instance;
int ret;
int limit;
};
typedef struct fcs_instance_item_struct fcs_instance_item_t;
struct fcs_user_struct
{
/*
* This is a list of several consecutive instances that are run
* one after the other in case the previous ones could not solve
* the board
* */
fcs_instance_item_t * instances_list;
int num_instances;
int max_num_instances;
int current_instance_idx;
/*
* The global (sequence-wide) limit of the iterations. Used
* by limit_iterations() and friends
* */
int current_iterations_limit;
/*
* The number of iterations this board started at.
* */
int iterations_board_started_at;
/*
* The number of iterations that the current instance started solving from.
* */
int init_num_times;
/*
* A pointer to the currently active instance out of the sequence
* */
freecell_solver_instance_t * instance;
fcs_state_with_locations_t state;
fcs_state_with_locations_t running_state;
int ret;
int state_validity_ret;
fcs_card_t state_validity_card;
freecell_solver_user_iter_handler_t iter_handler;
void * iter_handler_context;
freecell_solver_soft_thread_t * soft_thread;
#ifdef INDIRECT_STACK_STATES
fcs_card_t indirect_stacks_buffer[MAX_NUM_STACKS << 7];
#endif
char * state_string_copy;
fcs_preset_t common_preset;
};
typedef struct fcs_user_struct fcs_user_t;
static void user_initialize(
fcs_user_t * ret
)
{
const fcs_preset_t * freecell_preset;
freecell_solver_get_preset_by_name(
"freecell",
&freecell_preset
);
fcs_duplicate_preset(ret->common_preset, *freecell_preset);
ret->max_num_instances = 10;
ret->instances_list = malloc(sizeof(ret->instances_list[0]) * ret->max_num_instances);
ret->num_instances = 1;
ret->current_instance_idx = 0;
ret->instance = freecell_solver_alloc_instance();
freecell_solver_apply_preset_by_ptr(ret->instance, &(ret->common_preset));
ret->instances_list[ret->current_instance_idx].instance = ret->instance;
ret->instances_list[ret->current_instance_idx].ret = ret->ret = FCS_STATE_NOT_BEGAN_YET;
ret->instances_list[ret->current_instance_idx].limit = -1;
ret->current_iterations_limit = -1;
ret->soft_thread =
freecell_solver_instance_get_soft_thread(
ret->instance, 0,0
);
ret->state_string_copy = NULL;
ret->iterations_board_started_at = 0;
}
void * freecell_solver_user_alloc(void)
{
fcs_user_t * ret;
ret = (fcs_user_t *)malloc(sizeof(fcs_user_t));
user_initialize(ret);
return (void*)ret;
}
int freecell_solver_user_apply_preset(
void * user_instance,
const char * preset_name)
{
const fcs_preset_t * new_preset_ptr;
fcs_user_t * user;
int status;
int i;
user = (fcs_user_t*)user_instance;
status =
freecell_solver_get_preset_by_name(
preset_name,
&new_preset_ptr
);
if (status != FCS_PRESET_CODE_OK)
{
return status;
}
for(i = 0 ; i < user->num_instances ; i++)
{
status = freecell_solver_apply_preset_by_ptr(
user->instances_list[i].instance,
new_preset_ptr
);
if (status != FCS_PRESET_CODE_OK)
{
return status;
}
}
fcs_duplicate_preset(user->common_preset, *new_preset_ptr);
return FCS_PRESET_CODE_OK;
}
void freecell_solver_user_limit_iterations(
void * user_instance,
int max_iters
)
{
fcs_user_t * user;
user = (fcs_user_t*)user_instance;
user->current_iterations_limit = max_iters;
}
void freecell_solver_user_limit_current_instance_iterations(
void * user_instance,
int max_iters
)
{
fcs_user_t * user;
user = (fcs_user_t*)user_instance;
user->instances_list[user->current_instance_idx].limit = max_iters;
}
#ifndef min
#define min(a,b) (((a)<(b))?(a):(b))
#endif
int freecell_solver_user_set_tests_order(
void * user_instance,
const char * tests_order,
char * * error_string
)
{
fcs_user_t * user;
user = (fcs_user_t*)user_instance;
return
freecell_solver_apply_tests_order(
&(user->soft_thread->tests_order),
tests_order,
error_string
);
}
int freecell_solver_user_solve_board(
void * user_instance,
const char * state_as_string
)
{
fcs_user_t * user;
user = (fcs_user_t*)user_instance;
user->state_string_copy = strdup(state_as_string);
user->current_instance_idx = 0;
return freecell_solver_user_resume_solution(user_instance);
}
static void recycle_instance(
fcs_user_t * user,
int i
)
{
if (user->instances_list[i].ret == FCS_STATE_WAS_SOLVED)
{
fcs_move_stack_destroy(user->instance->solution_moves);
user->instance->solution_moves = NULL;
}
else if (user->instances_list[i].ret == FCS_STATE_SUSPEND_PROCESS)
{
freecell_solver_unresume_instance(user->instances_list[i].instance);
}
if (user->instances_list[i].ret != FCS_STATE_NOT_BEGAN_YET)
{
freecell_solver_recycle_instance(user->instances_list[i].instance);
/*
* We have to initialize init_num_times to 0 here, because it may not
* get initialized again, and now the num_times of the instance
* is equal to 0.
* */
user->init_num_times = 0;
}
user->instances_list[i].ret = FCS_STATE_NOT_BEGAN_YET;
}
int freecell_solver_user_resume_solution(
void * user_instance
)
{
int init_num_times;
int run_for_first_iteration = 1;
int ret;
fcs_user_t * user;
user = (fcs_user_t*)user_instance;
/*
* I expect user->current_instance_idx to be initialized at some value.
* */
for( ;
run_for_first_iteration || ((user->current_instance_idx < user->num_instances) && (ret == FCS_STATE_IS_NOT_SOLVEABLE)) ;
recycle_instance(user, user->current_instance_idx), user->current_instance_idx++
)
{
run_for_first_iteration = 0;
user->instance = user->instances_list[user->current_instance_idx].instance;
if (user->instances_list[user->current_instance_idx].ret == FCS_STATE_NOT_BEGAN_YET)
{
int status;
status = freecell_solver_initial_user_state_to_c(
user->state_string_copy,
&(user->state),
user->instance->freecells_num,
user->instance->stacks_num,
user->instance->decks_num
#ifdef FCS_WITH_TALONS
,user->instance->talon_type
#endif
#ifdef INDIRECT_STACK_STATES
,user->indirect_stacks_buffer
#endif
);
if (status != FCS_USER_STATE_TO_C__SUCCESS)
{
user->ret = FCS_STATE_INVALID_STATE;
user->state_validity_ret = FCS_STATE_VALIDITY__PREMATURE_END_OF_INPUT;
return user->ret;
}
user->state_validity_ret = freecell_solver_check_state_validity(
&user->state,
user->instance->freecells_num,
user->instance->stacks_num,
user->instance->decks_num,
#ifdef FCS_WITH_TALONS
FCS_TALON_NONE,
#endif
&(user->state_validity_card));
if (user->state_validity_ret != 0)
{
user->ret = FCS_STATE_INVALID_STATE;
return user->ret;
}
/* running_state is a normalized state. So I'm duplicating
* state to it before state is canonized
* */
fcs_duplicate_state(user->running_state, user->state);
fcs_canonize_state(
&user->state,
user->instance->freecells_num,
user->instance->stacks_num
);
freecell_solver_init_instance(user->instance);
#define global_limit() \
(user->instance->num_times + user->current_iterations_limit - user->iterations_board_started_at)
#define local_limit() \
(user->instances_list[user->current_instance_idx].limit)
#define min(a,b) (((a)<(b))?(a):(b))
#define calc_max_iters() \
{ \
if (user->instances_list[user->current_instance_idx].limit < 0) \
{\
if (user->current_iterations_limit < 0)\
{\
user->instance->max_num_times = -1;\
}\
else\
{\
user->instance->max_num_times = global_limit();\
}\
}\
else\
{\
if (user->current_iterations_limit < 0)\
{\
user->instance->max_num_times = local_limit();\
}\
else\
{\
int a, b;\
\
a = global_limit();\
b = local_limit();\
\
user->instance->max_num_times = min(a,b);\
}\
}\
}
calc_max_iters();
user->init_num_times = init_num_times = user->instance->num_times;
ret = user->ret =
user->instances_list[user->current_instance_idx].ret =
freecell_solver_solve_instance(user->instance, &user->state);
}
else
{
calc_max_iters();
user->init_num_times = init_num_times = user->instance->num_times;
ret = user->ret =
user->instances_list[user->current_instance_idx].ret =
freecell_solver_resume_instance(user->instance);
}
user->iterations_board_started_at += user->instance->num_times - init_num_times;
user->init_num_times = user->instance->num_times;
if (user->ret == FCS_STATE_WAS_SOLVED)
{
freecell_solver_move_stack_normalize(
user->instance->solution_moves,
&(user->state),
user->instance->freecells_num,
user->instance->stacks_num,
user->instance->decks_num
);
break;
}
else if (user->ret == FCS_STATE_SUSPEND_PROCESS)
{
/*
* First - check if we exceeded our limit. If so - we must terminate
* and return now.
* */
if ((user->current_iterations_limit >= 0) &&
(user->iterations_board_started_at >= user->current_iterations_limit))
{
break;
}
/*
* Determine if we exceeded the instance-specific quota and if
* so, designate it as unsolvable.
* */
if ((local_limit() >= 0) &&
(user->instance->num_times >= local_limit())
)
{
ret = FCS_STATE_IS_NOT_SOLVEABLE;
}
}
}
return ret;
}
int freecell_solver_user_get_next_move(
void * user_instance,
fcs_move_t * move
)
{
fcs_user_t * user;
user = (fcs_user_t*)user_instance;
if (user->ret == FCS_STATE_WAS_SOLVED)
{
int ret;
ret = fcs_move_stack_pop(
user->instance->solution_moves,
move
);
if (ret == 0)
{
freecell_solver_apply_move(
&(user->running_state),
*move,
user->instance->freecells_num,
user->instance->stacks_num,
user->instance->decks_num
);
}
return ret;
}
else
{
return 1;
}
}
char * freecell_solver_user_current_state_as_string(
void * user_instance,
int parseable_output,
int canonized_order_output,
int display_10_as_t
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
return
freecell_solver_state_as_string(
&(user->running_state),
user->instance->freecells_num,
user->instance->stacks_num,
user->instance->decks_num,
parseable_output,
canonized_order_output,
display_10_as_t
);
}
static void user_free_resources(
fcs_user_t * user
)
{
int i;
for(i=0;i<user->num_instances;i++)
{
int ret_code = user->instances_list[i].ret;
if (ret_code == FCS_STATE_WAS_SOLVED)
{
fcs_move_stack_destroy(user->instance->solution_moves);
user->instance->solution_moves = NULL;
}
else if (ret_code == FCS_STATE_SUSPEND_PROCESS)
{
freecell_solver_unresume_instance(user->instances_list[i].instance);
}
if (ret_code != FCS_STATE_NOT_BEGAN_YET)
{
if (ret_code != FCS_STATE_INVALID_STATE)
{
freecell_solver_finish_instance(user->instances_list[i].instance);
}
}
freecell_solver_free_instance(user->instances_list[i].instance);
}
free(user->instances_list);
if (user->state_string_copy != NULL)
{
free(user->state_string_copy);
user->state_string_copy = NULL;
}
}
void freecell_solver_user_free(
void * user_instance
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
user_free_resources(user);
free(user);
}
int freecell_solver_user_get_current_depth(
void * user_instance
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
return (user->soft_thread->num_solution_states - 1);
}
void freecell_solver_user_set_solving_method(
void * user_instance,
int method
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
user->soft_thread->method = method;
}
#define set_for_all_instances(what) \
{ \
for(i = 0 ; i < user->num_instances ; i++) \
{ \
user->instances_list[i].instance->what = what; \
} \
user->common_preset.what = what; \
}
int freecell_solver_user_set_num_freecells(
void * user_instance,
int freecells_num
)
{
fcs_user_t * user;
int i;
user = (fcs_user_t *)user_instance;
if ((freecells_num < 0) || (freecells_num > MAX_NUM_FREECELLS))
{
return 1;
}
set_for_all_instances(freecells_num);
return 0;
}
int freecell_solver_user_set_num_stacks(
void * user_instance,
int stacks_num
)
{
fcs_user_t * user;
int i;
user = (fcs_user_t *)user_instance;
if ((stacks_num < 0) || (stacks_num > MAX_NUM_STACKS))
{
return 1;
}
set_for_all_instances(stacks_num);
return 0;
}
int freecell_solver_user_set_num_decks(
void * user_instance,
int decks_num
)
{
fcs_user_t * user;
int i;
user = (fcs_user_t *)user_instance;
if ((decks_num < 0) || (decks_num > MAX_NUM_DECKS))
{
return 1;
}
set_for_all_instances(decks_num);
return 0;
}
int freecell_solver_user_set_game(
void * user_instance,
int freecells_num,
int stacks_num,
int decks_num,
int sequences_are_built_by,
int unlimited_sequence_move,
int empty_stacks_fill
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
if (freecell_solver_user_set_num_freecells(user_instance, freecells_num))
{
return 1;
}
if (freecell_solver_user_set_num_stacks(user_instance, stacks_num))
{
return 2;
}
if (freecell_solver_user_set_num_decks(user_instance, decks_num))
{
return 3;
}
if (freecell_solver_user_set_sequences_are_built_by_type(user_instance, sequences_are_built_by))
{
return 4;
}
if (freecell_solver_user_set_sequence_move(user_instance, unlimited_sequence_move))
{
return 5;
}
if (freecell_solver_user_set_empty_stacks_filled_by(user_instance, empty_stacks_fill))
{
return 6;
}
return 0;
}
int freecell_solver_user_get_num_times(void * user_instance)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
return user->iterations_board_started_at + user->instance->num_times - user->init_num_times;
}
int freecell_solver_user_get_limit_iterations(void * user_instance)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
return user->instance->max_num_times;
}
int freecell_solver_user_get_moves_left(void * user_instance)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
if (user->ret == FCS_STATE_WAS_SOLVED)
return user->instance->solution_moves->num_moves;
else
return 0;
}
void freecell_solver_user_set_solution_optimization(
void * user_instance,
int optimize
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
user->instance->optimize_solution_path = optimize;
}
char * freecell_solver_user_move_to_string(
fcs_move_t move,
int standard_notation
)
{
return freecell_solver_move_to_string(move, standard_notation);
}
char * freecell_solver_user_move_to_string_w_state(
void * user_instance,
fcs_move_t move,
int standard_notation
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
return
freecell_solver_move_to_string_w_state(
&(user->running_state),
user->instance->freecells_num,
user->instance->stacks_num,
user->instance->decks_num,
move,
standard_notation
);
}
void freecell_solver_user_limit_depth(
void * user_instance,
int max_depth
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
user->instance->max_depth = max_depth;
}
int freecell_solver_user_get_max_num_freecells(void)
{
return MAX_NUM_FREECELLS;
}
int freecell_solver_user_get_max_num_stacks(void)
{
return MAX_NUM_STACKS;
}
int freecell_solver_user_get_max_num_decks(void)
{
return MAX_NUM_DECKS;
}
char * freecell_solver_user_get_invalid_state_error_string(
void * user_instance,
int print_ts
)
{
fcs_user_t * user;
char string[80], card_str[10];
user = (fcs_user_t *)user_instance;
if (user->state_validity_ret == FCS_STATE_VALIDITY__OK)
{
return strdup("");
}
fcs_card_perl2user(user->state_validity_card, card_str, print_ts);
if (user->state_validity_ret == FCS_STATE_VALIDITY__EMPTY_SLOT)
{
sprintf(string, "%s",
"There's an empty slot in one of the stacks."
);
}
else if ((user->state_validity_ret == FCS_STATE_VALIDITY__EXTRA_CARD) ||
(user->state_validity_ret == FCS_STATE_VALIDITY__MISSING_CARD)
)
{
sprintf(string, "%s%s.",
((user->state_validity_ret == FCS_STATE_VALIDITY__EXTRA_CARD)? "There's an extra card: " : "There's a missing card: "),
card_str
);
}
else if (user->state_validity_ret == FCS_STATE_VALIDITY__PREMATURE_END_OF_INPUT)
{
sprintf(string, "%s.", "Not enough input");
}
return strdup(string);
}
int freecell_solver_user_set_sequences_are_built_by_type(
void * user_instance,
int sequences_are_built_by
)
{
fcs_user_t * user;
int i;
user = (fcs_user_t *)user_instance;
if ((sequences_are_built_by < 0) || (sequences_are_built_by > 2))
{
return 1;
}
set_for_all_instances(sequences_are_built_by)
return 0;
}
int freecell_solver_user_set_sequence_move(
void * user_instance,
int unlimited_sequence_move
)
{
fcs_user_t * user;
int i;
user = (fcs_user_t *)user_instance;
set_for_all_instances(unlimited_sequence_move);
return 0;
}
int freecell_solver_user_set_empty_stacks_filled_by(
void * user_instance,
int empty_stacks_fill
)
{
fcs_user_t * user;
int i;
user = (fcs_user_t *)user_instance;
if ((empty_stacks_fill < 0) || (empty_stacks_fill > 2))
{
return 1;
}
set_for_all_instances(empty_stacks_fill);
return 0;
}
int freecell_solver_user_set_a_star_weight(
void * user_instance,
int index,
double weight
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
if ((index < 0) || (index >= (int)(sizeof(user->soft_thread->a_star_weights)/sizeof(user->soft_thread->a_star_weights[0]))))
{
return 1;
}
if (weight < 0)
{
return 2;
}
user->soft_thread->a_star_weights[index] = weight;
return 0;
}
static void freecell_solver_user_iter_handler_wrapper(
void * user_instance,
int iter_num,
int depth,
void * lp_instance,
fcs_state_with_locations_t * ptr_state_with_locations,
int parent_iter_num
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
user->iter_handler(
user_instance,
iter_num,
depth,
(void *)ptr_state_with_locations,
parent_iter_num,
user->iter_handler_context
);
(void)lp_instance;
return;
}
void freecell_solver_user_set_iter_handler(
void * user_instance,
freecell_solver_user_iter_handler_t iter_handler,
void * iter_handler_context
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
if (iter_handler == NULL)
{
user->instance->debug_iter_output = 0;
}
else
{
/* Disable it temporarily while we change the settings */
user->instance->debug_iter_output = 0;
user->iter_handler = iter_handler;
user->iter_handler_context = iter_handler_context;
user->instance->debug_iter_output_context = user;
user->instance->debug_iter_output_func = freecell_solver_user_iter_handler_wrapper;
user->instance->debug_iter_output = 1;
}
}
char * freecell_solver_user_iter_state_as_string(
void * user_instance,
void * ptr_state,
int parseable_output,
int canonized_order_output,
int display_10_as_t
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
return
freecell_solver_state_as_string(
ptr_state,
user->instance->freecells_num,
user->instance->stacks_num,
user->instance->decks_num,
parseable_output,
canonized_order_output,
display_10_as_t
);
}
void freecell_solver_user_set_random_seed(
void * user_instance,
int seed
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
freecell_solver_rand_srand(user->soft_thread->rand_gen, (user->soft_thread->rand_seed = seed));
}
int freecell_solver_user_get_num_states_in_collection(void * user_instance)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
return user->instance->num_states_in_collection;
}
void freecell_solver_user_limit_num_states_in_collection(
void * user_instance,
int max_num_states
)
{
fcs_user_t * user;
user = (fcs_user_t*)user_instance;
user->instance->max_num_states_in_collection = max_num_states;
}
int freecell_solver_user_next_soft_thread(
void * user_instance
)
{
fcs_user_t * user;
freecell_solver_soft_thread_t * soft_thread;
user = (fcs_user_t *)user_instance;
soft_thread = freecell_solver_new_soft_thread(user->soft_thread);
if (soft_thread == NULL)
{
return 1;
}
user->soft_thread = soft_thread;
return 0;
}
extern void freecell_solver_user_set_soft_thread_step(
void * user_instance,
int num_times_step
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
user->soft_thread->num_times_step = num_times_step;
}
int freecell_solver_user_next_hard_thread(
void * user_instance
)
{
fcs_user_t * user;
freecell_solver_soft_thread_t * soft_thread;
user = (fcs_user_t *)user_instance;
soft_thread = freecell_solver_new_hard_thread(user->instance);
if (soft_thread == NULL)
{
return 1;
}
user->soft_thread = soft_thread;
return 0;
}
int freecell_solver_user_get_num_soft_threads_in_instance(
void * user_instance
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
return user->instance->next_soft_thread_id;
}
void freecell_solver_user_set_calc_real_depth(
void * user_instance,
int calc_real_depth
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
user->instance->calc_real_depth = calc_real_depth;
}
void freecell_solver_user_set_soft_thread_name(
void * user_instance,
char * name
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
if (user->soft_thread->name != NULL)
{
free(user->soft_thread->name);
}
user->soft_thread->name = strdup(name);
}
int freecell_solver_user_set_hard_thread_prelude(
void * user_instance,
char * prelude
)
{
fcs_user_t * user;
freecell_solver_hard_thread_t * hard_thread;
user = (fcs_user_t *)user_instance;
hard_thread = user->soft_thread->hard_thread;
if (hard_thread->prelude_as_string != NULL)
{
free(hard_thread->prelude_as_string);
hard_thread->prelude_as_string = NULL;
}
hard_thread->prelude_as_string = strdup(prelude);
return 0;
}
void freecell_solver_user_recycle(
void * user_instance
)
{
fcs_user_t * user;
int i;
user = (fcs_user_t *)user_instance;
for(i=0;i<user->num_instances;i++)
{
recycle_instance(user, i);
}
user->current_iterations_limit = -1;
user->iterations_board_started_at = 0;
if (user->state_string_copy != NULL)
{
free(user->state_string_copy);
user->state_string_copy = NULL;
}
}
int freecell_solver_user_set_optimization_scan_tests_order(
void * user_instance,
const char * tests_order,
char * * error_string
)
{
fcs_user_t * user;
int ret;
user = (fcs_user_t*)user_instance;
if (user->instance->opt_tests_order.tests)
{
free(user->instance->opt_tests_order.tests);
user->instance->opt_tests_order.tests = NULL;
}
user->instance->opt_tests_order_set = 0;
ret =
freecell_solver_apply_tests_order(
&(user->instance->opt_tests_order),
tests_order,
error_string
);
if (!ret)
{
user->instance->opt_tests_order_set = 1;
}
return ret;
}
void freecell_solver_user_set_reparent_states(
void * user_instance,
int to_reparent_states
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
user->instance->to_reparent_states = to_reparent_states;
}
void freecell_solver_user_set_scans_synergy(
void * user_instance,
int synergy
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
user->instance->scans_synergy = synergy;
}
int freecell_solver_user_next_instance(
void * user_instance
)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
user->num_instances++;
if (user->num_instances == user->max_num_instances)
{
user->max_num_instances += 10;
user->instances_list =
realloc(
user->instances_list,
sizeof(user->instances_list[0])*user->max_num_instances
);
}
user->current_instance_idx = user->num_instances-1;
user->instance = freecell_solver_alloc_instance();
freecell_solver_apply_preset_by_ptr(user->instance, &(user->common_preset));
/*
* Switch the soft_thread variable so it won't refer to the old
* instance
* */
user->soft_thread =
freecell_solver_instance_get_soft_thread(
user->instance, 0, 0
);
user->instances_list[user->current_instance_idx].instance = user->instance;
user->instances_list[user->current_instance_idx].ret = user->ret = FCS_STATE_NOT_BEGAN_YET;
user->instances_list[user->current_instance_idx].limit = -1;
return 0;
}
int freecell_solver_user_reset(void * user_instance)
{
fcs_user_t * user;
user = (fcs_user_t *)user_instance;
user_free_resources(user);
user_initialize(user);
return 0;
}