|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
#include "fcs_user.h"
|
|
|
|
#include "fcs_cl.h"
|
|
|
|
#include "cl_chop.h"
|
|
|
|
|
|
|
|
#include "prefix.h"
|
|
|
|
|
|
|
|
#ifdef DMALLOC
|
|
|
|
#include "dmalloc.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int read_preset(char * preset_name, args_man_t * * args, char * * opened_files_dir_to_assign, char * user_preset_dir)
|
|
|
|
{
|
|
|
|
int ret_code = 1;
|
|
|
|
char * home_dir_presetrc = NULL, * global_presetrc = NULL, * env_var_presetrc = NULL;
|
|
|
|
char * path;
|
|
|
|
char * * presetrc_pathes[5] = {&env_var_presetrc, &home_dir_presetrc, &global_presetrc, &user_preset_dir, NULL};
|
|
|
|
int path_idx;
|
|
|
|
char line[8192];
|
|
|
|
FILE * f = NULL;
|
|
|
|
char * fgets_ret;
|
|
|
|
char * opened_files_dir = NULL;
|
|
|
|
int read_next_preset = 0;
|
|
|
|
|
|
|
|
{
|
|
|
|
char * home_dir;
|
|
|
|
home_dir = getenv("HOME");
|
|
|
|
if (home_dir)
|
|
|
|
{
|
|
|
|
home_dir_presetrc = malloc(strlen(home_dir) + 50);
|
|
|
|
sprintf(home_dir_presetrc,
|
|
|
|
"%s/.freecell-solver/presetrc", home_dir
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
env_var_presetrc = getenv("FREECELL_SOLVER_PRESETRC");
|
|
|
|
|
|
|
|
global_presetrc = (FREECELL_SOLVER_PKG_DATA_DIR "/presetrc");
|
|
|
|
|
|
|
|
for(path_idx=0;(presetrc_pathes[path_idx] != NULL) ; path_idx++)
|
|
|
|
{
|
|
|
|
path = (*presetrc_pathes[path_idx]);
|
|
|
|
if (path == NULL)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
f = fopen(path, "rt");
|
|
|
|
if (f == NULL)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
while(1)
|
|
|
|
{
|
|
|
|
fgets_ret = fgets(line, sizeof(line), f);
|
|
|
|
if (fgets_ret == NULL)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!strncmp(line, "dir=", 4))
|
|
|
|
{
|
|
|
|
#define nullify_newline() \
|
|
|
|
{ \
|
|
|
|
char * s; \
|
|
|
|
\
|
|
|
|
s = strchr(line, '\n'); \
|
|
|
|
if (s != NULL) \
|
|
|
|
{ \
|
|
|
|
*s = '\0'; \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
nullify_newline();
|
|
|
|
|
|
|
|
if (opened_files_dir != NULL)
|
|
|
|
{
|
|
|
|
free(opened_files_dir);
|
|
|
|
}
|
|
|
|
opened_files_dir = strdup(line+4);
|
|
|
|
}
|
|
|
|
else if (!strncmp(line, "name=", 5))
|
|
|
|
{
|
|
|
|
nullify_newline();
|
|
|
|
if (!strcmp(line+5, preset_name))
|
|
|
|
{
|
|
|
|
read_next_preset = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!strncmp(line, "command=", 8))
|
|
|
|
{
|
|
|
|
if (read_next_preset)
|
|
|
|
{
|
|
|
|
*args = freecell_solver_args_man_alloc();
|
|
|
|
freecell_solver_args_man_chop(*args, line+8);
|
|
|
|
ret_code = 0;
|
|
|
|
goto HAVE_PRESET;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(f);
|
|
|
|
f = NULL;
|
|
|
|
#undef nullify_newline
|
|
|
|
}
|
|
|
|
HAVE_PRESET:
|
|
|
|
|
|
|
|
if (f)
|
|
|
|
{
|
|
|
|
fclose(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (home_dir_presetrc)
|
|
|
|
{
|
|
|
|
free(home_dir_presetrc);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret_code == 0)
|
|
|
|
{
|
|
|
|
*opened_files_dir_to_assign = opened_files_dir;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (opened_files_dir)
|
|
|
|
{
|
|
|
|
free(opened_files_dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret_code;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int freecell_solver_user_cmd_line_parse_args_with_file_nesting_count(
|
|
|
|
void * instance,
|
|
|
|
int argc,
|
|
|
|
const char * argv[],
|
|
|
|
int start_arg,
|
|
|
|
char * * known_parameters,
|
|
|
|
freecell_solver_user_cmd_line_known_commands_callback_t callback,
|
|
|
|
void * callback_context,
|
|
|
|
char * * error_string,
|
|
|
|
int * last_arg,
|
|
|
|
int file_nesting_count,
|
|
|
|
char * opened_files_dir
|
|
|
|
)
|
|
|
|
{
|
|
|
|
int arg;
|
|
|
|
char * * known_param;
|
|
|
|
int num_to_skip;
|
|
|
|
int callback_ret;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
*error_string = NULL;
|
|
|
|
|
|
|
|
for(arg=start_arg;arg<argc;arg++)
|
|
|
|
{
|
|
|
|
/* First check for the parameters that the user recognizes */
|
|
|
|
known_param = known_parameters;
|
|
|
|
while((*known_param) && strcmp(*known_param, argv[arg]))
|
|
|
|
{
|
|
|
|
known_param++;
|
|
|
|
}
|
|
|
|
if ((*known_param) != NULL )
|
|
|
|
{
|
|
|
|
callback_ret = callback(instance, argc, argv, arg, &num_to_skip, &ret, callback_context);
|
|
|
|
if (callback_ret == FCS_CMD_LINE_SKIP)
|
|
|
|
{
|
|
|
|
arg += num_to_skip-1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (callback_ret == FCS_CMD_LINE_STOP)
|
|
|
|
{
|
|
|
|
*last_arg = arg;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "-md")) || (!strcmp(argv[arg], "--max-depth")))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
freecell_solver_user_limit_depth(instance, atoi(argv[arg]));
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "-mi")) || (!strcmp(argv[arg], "--max-iters")))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
freecell_solver_user_limit_current_instance_iterations(instance, atoi(argv[arg]));
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "-to")) || (!strcmp(argv[arg], "--tests-order")))
|
|
|
|
{
|
|
|
|
char * fcs_user_errstr;
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
ret = freecell_solver_user_set_tests_order(instance, argv[arg], &fcs_user_errstr);
|
|
|
|
if (ret != 0)
|
|
|
|
{
|
|
|
|
char * errstr = malloc(strlen(fcs_user_errstr)+500);
|
|
|
|
sprintf(
|
|
|
|
errstr,
|
|
|
|
"Error in tests' order!\n%s\n",
|
|
|
|
fcs_user_errstr
|
|
|
|
);
|
|
|
|
free(fcs_user_errstr);
|
|
|
|
|
|
|
|
*error_string = errstr;
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "--freecells-num")))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
if (freecell_solver_user_set_num_freecells(instance, atoi(argv[arg])) != 0)
|
|
|
|
{
|
|
|
|
char * errstr;
|
|
|
|
|
|
|
|
errstr = malloc(500);
|
|
|
|
sprintf(errstr,
|
|
|
|
"Error! The freecells\' number "
|
|
|
|
"exceeds the maximum of %i.\n"
|
|
|
|
"Recompile the program if you wish to have more.\n",
|
|
|
|
freecell_solver_user_get_max_num_freecells()
|
|
|
|
);
|
|
|
|
|
|
|
|
*error_string = errstr;
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "--stacks-num")))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
if (freecell_solver_user_set_num_stacks(instance, atoi(argv[arg])) != 0)
|
|
|
|
{
|
|
|
|
char * errstr;
|
|
|
|
|
|
|
|
errstr = malloc(500);
|
|
|
|
sprintf(errstr,
|
|
|
|
"Error! The stacks\' number "
|
|
|
|
"exceeds the maximum of %i.\n"
|
|
|
|
"Recompile the program if you wish to have more.\n",
|
|
|
|
freecell_solver_user_get_max_num_stacks()
|
|
|
|
);
|
|
|
|
|
|
|
|
*error_string = errstr;
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "--decks-num")))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
if (freecell_solver_user_set_num_decks(instance, atoi(argv[arg])) != 0)
|
|
|
|
{
|
|
|
|
char * errstr;
|
|
|
|
|
|
|
|
errstr = malloc(500);
|
|
|
|
sprintf(errstr,
|
|
|
|
"Error! The decks\' number "
|
|
|
|
"exceeds the maximum of %i.\n"
|
|
|
|
"Recopmile the program if you wish to have more.\n",
|
|
|
|
freecell_solver_user_get_max_num_decks()
|
|
|
|
);
|
|
|
|
|
|
|
|
*error_string = errstr;
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "--sequences-are-built-by")))
|
|
|
|
{
|
|
|
|
int sbb;
|
|
|
|
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(argv[arg], "suit"))
|
|
|
|
{
|
|
|
|
sbb = FCS_SEQ_BUILT_BY_SUIT;
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[arg], "rank"))
|
|
|
|
{
|
|
|
|
sbb = FCS_SEQ_BUILT_BY_RANK;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sbb = FCS_SEQ_BUILT_BY_ALTERNATE_COLOR;
|
|
|
|
}
|
|
|
|
freecell_solver_user_set_sequences_are_built_by_type(instance, sbb);
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "--sequence-move")))
|
|
|
|
{
|
|
|
|
int unlimited;
|
|
|
|
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(argv[arg], "unlimited"))
|
|
|
|
{
|
|
|
|
unlimited = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unlimited = 0;
|
|
|
|
}
|
|
|
|
freecell_solver_user_set_sequence_move(instance, unlimited);
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[arg], "--empty-stacks-filled-by"))
|
|
|
|
{
|
|
|
|
int es_fill;
|
|
|
|
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(argv[arg], "kings"))
|
|
|
|
{
|
|
|
|
es_fill = FCS_ES_FILLED_BY_KINGS_ONLY;
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[arg], "none"))
|
|
|
|
{
|
|
|
|
es_fill = FCS_ES_FILLED_BY_NONE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
es_fill = FCS_ES_FILLED_BY_ANY_CARD;
|
|
|
|
}
|
|
|
|
freecell_solver_user_set_empty_stacks_filled_by(
|
|
|
|
instance,
|
|
|
|
es_fill
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else if (
|
|
|
|
(!strcmp(argv[arg], "--game")) ||
|
|
|
|
(!strcmp(argv[arg], "--preset")) ||
|
|
|
|
(!strcmp(argv[arg], "-g"))
|
|
|
|
)
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = freecell_solver_user_apply_preset(instance, argv[arg]);
|
|
|
|
if (ret == FCS_PRESET_CODE_NOT_FOUND)
|
|
|
|
{
|
|
|
|
char * errstr;
|
|
|
|
|
|
|
|
errstr = malloc(strlen(argv[arg])+500);
|
|
|
|
|
|
|
|
sprintf(errstr, "Unknown game \"%s\"!\n\n", argv[arg]);
|
|
|
|
*error_string = errstr;
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
else if (ret == FCS_PRESET_CODE_FREECELLS_EXCEED_MAX)
|
|
|
|
{
|
|
|
|
char * errstr;
|
|
|
|
|
|
|
|
errstr = malloc(strlen(argv[arg])+500);
|
|
|
|
sprintf(errstr, "The game \"%s\" exceeds the maximal number "
|
|
|
|
"of freecells in the program.\n"
|
|
|
|
"Modify the file \"config.h\" and recompile, "
|
|
|
|
"if you wish to solve one of its boards.\n",
|
|
|
|
argv[arg]
|
|
|
|
);
|
|
|
|
|
|
|
|
*error_string = errstr;
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
else if (ret == FCS_PRESET_CODE_STACKS_EXCEED_MAX)
|
|
|
|
{
|
|
|
|
char * errstr;
|
|
|
|
|
|
|
|
errstr = malloc(strlen(argv[arg])+500);
|
|
|
|
|
|
|
|
sprintf(errstr, "The game \"%s\" exceeds the maximal number "
|
|
|
|
"of stacks in the program.\n"
|
|
|
|
"Modify the file \"config.h\" and recompile, "
|
|
|
|
"if you wish to solve one of its boards.\n",
|
|
|
|
argv[arg]
|
|
|
|
);
|
|
|
|
|
|
|
|
*error_string = errstr;
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
else if (ret != FCS_PRESET_CODE_OK)
|
|
|
|
{
|
|
|
|
char * errstr;
|
|
|
|
|
|
|
|
errstr = malloc(strlen(argv[arg])+500);
|
|
|
|
|
|
|
|
sprintf(errstr,
|
|
|
|
"The game \"%s\" exceeds the limits of the program.\n"
|
|
|
|
"Modify the file \"config.h\" and recompile, if you wish to solve one of its boards.\n",
|
|
|
|
argv[arg]
|
|
|
|
);
|
|
|
|
|
|
|
|
*error_string = errstr;
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "-me")) || (!strcmp(argv[arg], "--method")))
|
|
|
|
{
|
|
|
|
int method;
|
|
|
|
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
if (!strcmp(argv[arg], "dfs"))
|
|
|
|
{
|
|
|
|
method = FCS_METHOD_HARD_DFS;
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[arg], "soft-dfs"))
|
|
|
|
{
|
|
|
|
method = FCS_METHOD_SOFT_DFS;
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[arg], "bfs"))
|
|
|
|
{
|
|
|
|
method = FCS_METHOD_BFS;
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[arg], "a-star"))
|
|
|
|
{
|
|
|
|
method = FCS_METHOD_A_STAR;
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[arg], "random-dfs"))
|
|
|
|
{
|
|
|
|
method = FCS_METHOD_RANDOM_DFS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char * errstr;
|
|
|
|
|
|
|
|
errstr = malloc(strlen(argv[arg])+500);
|
|
|
|
|
|
|
|
sprintf(
|
|
|
|
errstr,
|
|
|
|
"Unknown solving method \"%s\".\n",
|
|
|
|
argv[arg]
|
|
|
|
);
|
|
|
|
|
|
|
|
*error_string = errstr;
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
freecell_solver_user_set_solving_method(instance, method);
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "-asw")) || (!strcmp(argv[arg], "--a-star-weights")))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
{
|
|
|
|
int a;
|
|
|
|
const char * start_num;
|
|
|
|
const char * end_num;
|
|
|
|
char * num_copy;
|
|
|
|
start_num = argv[arg];
|
|
|
|
for(a=0;a<5;a++)
|
|
|
|
{
|
|
|
|
while ((*start_num > '9') && (*start_num < '0') && (*start_num != '\0'))
|
|
|
|
{
|
|
|
|
start_num++;
|
|
|
|
}
|
|
|
|
if (*start_num == '\0')
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
end_num = start_num+1;
|
|
|
|
while ((((*end_num >= '0') && (*end_num <= '9')) || (*end_num == '.')) && (*end_num != '\0'))
|
|
|
|
{
|
|
|
|
end_num++;
|
|
|
|
}
|
|
|
|
num_copy = malloc(end_num-start_num+1);
|
|
|
|
memcpy(num_copy, start_num, end_num-start_num);
|
|
|
|
num_copy[end_num-start_num] = '\0';
|
|
|
|
freecell_solver_user_set_a_star_weight(
|
|
|
|
instance,
|
|
|
|
a,
|
|
|
|
atof(num_copy)
|
|
|
|
);
|
|
|
|
free(num_copy);
|
|
|
|
start_num=end_num+1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "-opt")) || (!strcmp(argv[arg], "--optimize-solution")))
|
|
|
|
{
|
|
|
|
freecell_solver_user_set_solution_optimization(instance, 1);
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "-seed")))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
freecell_solver_user_set_random_seed(instance, atoi(argv[arg]));
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "-mss")) || (!strcmp(argv[arg], "--max-stored-states")))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
freecell_solver_user_limit_num_states_in_collection(
|
|
|
|
instance,
|
|
|
|
atoi(argv[arg])
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else if (
|
|
|
|
(!strcmp(argv[arg], "-nst")) ||
|
|
|
|
(!strcmp(argv[arg], "--next-soft-thread")) ||
|
|
|
|
(!strcmp(argv[arg], "-nht")) ||
|
|
|
|
(!strcmp(argv[arg], "--next-hard-thread"))
|
|
|
|
)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
int is_st = ((!strcmp(argv[arg], "-nst")) || (!strcmp(argv[arg], "--next-soft-thread")));
|
|
|
|
|
|
|
|
ret =
|
|
|
|
is_st ?
|
|
|
|
freecell_solver_user_next_soft_thread(instance) :
|
|
|
|
freecell_solver_user_next_hard_thread(instance)
|
|
|
|
;
|
|
|
|
|
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
char * errstr;
|
|
|
|
|
|
|
|
errstr = strdup("The maximal number of soft threads has been exceeded\n");
|
|
|
|
|
|
|
|
*error_string = errstr;
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "-step")) || (!strcmp(argv[arg], "--soft-thread-step")))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
freecell_solver_user_set_soft_thread_step(
|
|
|
|
instance,
|
|
|
|
atoi(argv[arg])
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "--reparent-states")))
|
|
|
|
{
|
|
|
|
freecell_solver_user_set_reparent_states(
|
|
|
|
instance,
|
|
|
|
1
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "--calc-real-depth")))
|
|
|
|
{
|
|
|
|
freecell_solver_user_set_calc_real_depth(
|
|
|
|
instance,
|
|
|
|
1);
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "--st-name")))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
freecell_solver_user_set_soft_thread_name(instance, (char*)argv[arg]);
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "--prelude")))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
freecell_solver_user_set_hard_thread_prelude(instance, (char*)argv[arg]);
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "-opt-to")) || (!strcmp(argv[arg], "--optimization-tests-order")))
|
|
|
|
{
|
|
|
|
char * fcs_user_errstr;
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = freecell_solver_user_set_optimization_scan_tests_order(
|
|
|
|
instance,
|
|
|
|
argv[arg],
|
|
|
|
&fcs_user_errstr
|
|
|
|
);
|
|
|
|
|
|
|
|
if (ret != 0)
|
|
|
|
{
|
|
|
|
char * errstr = malloc(strlen(fcs_user_errstr)+500);
|
|
|
|
sprintf(
|
|
|
|
errstr,
|
|
|
|
"Error in the optimization scan's tests' order!\n%s\n",
|
|
|
|
fcs_user_errstr
|
|
|
|
);
|
|
|
|
free(fcs_user_errstr);
|
|
|
|
|
|
|
|
*error_string = errstr;
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "--scans-synergy")))
|
|
|
|
{
|
|
|
|
int value;
|
|
|
|
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(argv[arg], "none"))
|
|
|
|
{
|
|
|
|
value = 0;
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[arg], "dead-end-marks"))
|
|
|
|
{
|
|
|
|
value = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char * errstr;
|
|
|
|
|
|
|
|
errstr = malloc(strlen(argv[arg])+500);
|
|
|
|
|
|
|
|
sprintf(errstr, "Unknown scans' synergy type \"%s\"!\n", argv[arg]);
|
|
|
|
*last_arg = arg;
|
|
|
|
*error_string = errstr;
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
freecell_solver_user_set_scans_synergy(
|
|
|
|
instance,
|
|
|
|
value
|
|
|
|
);
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "-ni")) ||
|
|
|
|
(!strcmp(argv[arg], "--next-instance")))
|
|
|
|
{
|
|
|
|
freecell_solver_user_next_instance(instance);
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[arg], "--reset"))
|
|
|
|
{
|
|
|
|
freecell_solver_user_reset(instance);
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[arg], "--read-from-file"))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
if (file_nesting_count == 0)
|
|
|
|
{
|
|
|
|
/* do nothing */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int num_to_skip = 0;
|
|
|
|
const char * s;
|
|
|
|
char * buffer;
|
|
|
|
FILE * f;
|
|
|
|
long file_len;
|
|
|
|
int ret;
|
|
|
|
size_t num_read;
|
|
|
|
args_man_t * args_man;
|
|
|
|
|
|
|
|
s = argv[arg];
|
|
|
|
while(isdigit(*s))
|
|
|
|
{
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
if (*s == ',')
|
|
|
|
{
|
|
|
|
num_to_skip = atoi(argv[arg]);
|
|
|
|
s++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (opened_files_dir)
|
|
|
|
{
|
|
|
|
char * complete_path;
|
|
|
|
|
|
|
|
complete_path = malloc(strlen(opened_files_dir)+strlen(s)+1);
|
|
|
|
sprintf(complete_path, "%s%s", opened_files_dir, s);
|
|
|
|
f = fopen(complete_path, "rt");
|
|
|
|
free(complete_path);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Initialize f to NULL so it will be initialized
|
|
|
|
* */
|
|
|
|
f = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Try to open from the local path */
|
|
|
|
if (f == NULL)
|
|
|
|
{
|
|
|
|
f = fopen(s, "rt");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we still could not open it return an error */
|
|
|
|
if (f == NULL)
|
|
|
|
{
|
|
|
|
char * err_str;
|
|
|
|
|
|
|
|
err_str = malloc(strlen(s)+100);
|
|
|
|
sprintf(err_str,
|
|
|
|
"Could not open file \"%s\"!\nQuitting.\n",
|
|
|
|
s);
|
|
|
|
|
|
|
|
*error_string = err_str;
|
|
|
|
*last_arg = arg;
|
|
|
|
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
fseek(f, 0, SEEK_END);
|
|
|
|
file_len = ftell(f);
|
|
|
|
buffer=malloc(file_len+1);
|
|
|
|
if (buffer == NULL)
|
|
|
|
{
|
|
|
|
*error_string = strdup("Could not allocate enough memory to parse the file. Quitting.\n");
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
fseek(f,0,SEEK_SET);
|
|
|
|
num_read = fread(buffer, 1, file_len, f);
|
|
|
|
fclose(f);
|
|
|
|
buffer[num_read] = '\0';
|
|
|
|
|
|
|
|
args_man = freecell_solver_args_man_alloc();
|
|
|
|
ret = freecell_solver_args_man_chop(args_man, buffer);
|
|
|
|
free(buffer);
|
|
|
|
if (ret != 0)
|
|
|
|
{
|
|
|
|
*error_string =
|
|
|
|
strdup("Could not parse the file. Quitting\n");
|
|
|
|
freecell_solver_args_man_free(args_man);
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (num_to_skip >= args_man->argc)
|
|
|
|
{
|
|
|
|
/* Do nothing */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = freecell_solver_user_cmd_line_parse_args_with_file_nesting_count(
|
|
|
|
instance,
|
|
|
|
args_man->argc - num_to_skip,
|
|
|
|
(const char **)(args_man->argv + num_to_skip),
|
|
|
|
0,
|
|
|
|
known_parameters,
|
|
|
|
callback,
|
|
|
|
callback_context,
|
|
|
|
error_string,
|
|
|
|
last_arg,
|
|
|
|
((file_nesting_count < 0) ? file_nesting_count : (file_nesting_count-1)),
|
|
|
|
opened_files_dir
|
|
|
|
);
|
|
|
|
|
|
|
|
if (ret == FCS_CMD_LINE_UNRECOGNIZED_OPTION)
|
|
|
|
{
|
|
|
|
/* Do nothing - continue */
|
|
|
|
}
|
|
|
|
else if (ret != FCS_CMD_LINE_OK)
|
|
|
|
{
|
|
|
|
freecell_solver_args_man_free(args_man);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
freecell_solver_args_man_free(args_man);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((!strcmp(argv[arg], "-l")) || (!strcmp(argv[arg], "--load-config")))
|
|
|
|
{
|
|
|
|
arg++;
|
|
|
|
if (arg == argc)
|
|
|
|
{
|
|
|
|
*last_arg = arg-1;
|
|
|
|
return FCS_CMD_LINE_PARAM_WITH_NO_ARG;
|
|
|
|
}
|
|
|
|
{
|
|
|
|
int status;
|
|
|
|
args_man_t * preset_args = 0;
|
|
|
|
char * dir = NULL;
|
|
|
|
|
|
|
|
status = read_preset((char*)argv[arg], &preset_args, &dir, NULL);
|
|
|
|
if (status != 0)
|
|
|
|
{
|
|
|
|
char * err_str;
|
|
|
|
err_str = malloc(strlen(argv[arg]) + 100);
|
|
|
|
sprintf(err_str, "Unable to load the \"%s\" configuration!\n", argv[arg]);
|
|
|
|
*error_string = err_str;
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
|
|
|
|
return FCS_CMD_LINE_ERROR_IN_ARG;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = freecell_solver_user_cmd_line_parse_args_with_file_nesting_count(
|
|
|
|
instance,
|
|
|
|
preset_args->argc,
|
|
|
|
(const char**)preset_args->argv,
|
|
|
|
0,
|
|
|
|
known_parameters,
|
|
|
|
callback,
|
|
|
|
callback_context,
|
|
|
|
error_string,
|
|
|
|
last_arg,
|
|
|
|
((file_nesting_count < 0) ? file_nesting_count : (file_nesting_count-1)),
|
|
|
|
dir ? dir : opened_files_dir
|
|
|
|
);
|
|
|
|
|
|
|
|
if (dir)
|
|
|
|
{
|
|
|
|
free(dir);
|
|
|
|
}
|
|
|
|
freecell_solver_args_man_free(preset_args);
|
|
|
|
|
|
|
|
if (ret == FCS_CMD_LINE_UNRECOGNIZED_OPTION)
|
|
|
|
{
|
|
|
|
/* Do nothing - continue */
|
|
|
|
}
|
|
|
|
else if (ret != FCS_CMD_LINE_OK)
|
|
|
|
{
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*last_arg = arg;
|
|
|
|
return FCS_CMD_LINE_UNRECOGNIZED_OPTION;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*last_arg = arg;
|
|
|
|
return FCS_CMD_LINE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int freecell_solver_user_cmd_line_parse_args(
|
|
|
|
void * instance,
|
|
|
|
int argc,
|
|
|
|
const char * argv[],
|
|
|
|
int start_arg,
|
|
|
|
char * * known_parameters,
|
|
|
|
freecell_solver_user_cmd_line_known_commands_callback_t callback,
|
|
|
|
void * callback_context,
|
|
|
|
char * * error_string,
|
|
|
|
int * last_arg
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return freecell_solver_user_cmd_line_parse_args_with_file_nesting_count(
|
|
|
|
instance,
|
|
|
|
argc,
|
|
|
|
argv,
|
|
|
|
start_arg,
|
|
|
|
known_parameters,
|
|
|
|
callback,
|
|
|
|
callback_context,
|
|
|
|
error_string,
|
|
|
|
last_arg,
|
|
|
|
-1,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|