nissy-nx

A Rubik's cube optimal solver
git clone https://git.tronto.net/nissy-nx
Download | Log | Files | Refs | README | LICENSE

commands.c (6843B)


      1 #define COMMANDS_C
      2 
      3 #include "commands.h"
      4 
      5 static bool             read_scramble(int c, char **v, CommandArgs *args);
      6 
      7 /* Arg parsing functions implementation **************************************/
      8 
      9 CommandArgs *
     10 solve_parse_args(int c, char **v)
     11 {
     12 	int i;
     13 	bool infinitesols, fixedmsols;
     14 	long val;
     15 
     16 	CommandArgs *a = new_args();
     17 
     18 	a->opts->min_moves     = 0;
     19 	a->opts->max_moves     = 20;
     20 	a->opts->max_solutions = 1;
     21 	a->opts->nthreads      = 1;
     22 	a->opts->optimal       = -1;
     23 	a->opts->can_niss      = false;
     24 	a->opts->verbose       = false;
     25 	a->opts->all           = false;
     26 	a->opts->print_number  = true;
     27 	a->opts->count_only    = false;
     28 
     29 	fixedmsols = false;
     30 	infinitesols = false;
     31 
     32 	for (i = 0; i < c; i++) {
     33 		if (!strcmp(v[i], "-m") && i+1 < c) {
     34 			val = strtol(v[++i], NULL, 10);
     35 			if (val < 0 || val > 100) {
     36 				fprintf(stderr,
     37 					"Invalid min number of moves"
     38 					"(0 <= N <= 100).\n");
     39 				return a;
     40 			}
     41 			a->opts->min_moves = val;
     42 		} else if (!strcmp(v[i], "-M") && i+1 < c) {
     43 			val = strtol(v[++i], NULL, 10);
     44 			if (val < 0 || val > 100) {
     45 				fprintf(stderr,
     46 					"Invalid max number of moves"
     47 					"(0 <= N <= 100).\n");
     48 				return a;
     49 			}
     50 			a->opts->max_moves = val;
     51 			infinitesols = true;
     52 		} else if (!strcmp(v[i], "-t") && i+1 < c) {
     53 			val = strtol(v[++i], NULL, 10);
     54 			if (val < 1 || val > 64) {
     55 				fprintf(stderr,
     56 					"Invalid number of threads."
     57 					"1 <= t <= 64\n");
     58 				return a;
     59 			}
     60 			a->opts->nthreads = val;
     61 		} else if (!strcmp(v[i], "-n") && i+1 < c) {
     62 			val = strtol(v[++i], NULL, 10);
     63 			if (val < 1 || val > 1000000) {
     64 				fprintf(stderr,
     65 					"Invalid number of solutions.\n");
     66 				return a;
     67 			}
     68 			a->opts->max_solutions = val;
     69 			fixedmsols = true;
     70 		} else if (!strcmp(v[i], "-o")) {
     71 			a->opts->optimal = 0;
     72 			infinitesols = true;
     73 		} else if (!strcmp(v[i], "-O") && i+1 < c) {
     74 			val = strtol(v[++i], NULL, 10);
     75 			if (val < 0 || val > 100 ||
     76 			    (val == 0 && strcmp("0", v[i]))) {
     77 				fprintf(stderr,
     78 					"Invalid max number of moves"
     79 					" (0 <= N <= 100).\n");
     80 				return a;
     81 			}
     82 			a->opts->optimal = val;
     83 			infinitesols = true;
     84 		} else if (!strcmp(v[i], "-i")) {
     85 			a->scrstdin = true;
     86 		} else if (!strcmp(v[i], "-v")) {
     87 			a->opts->verbose = true;
     88 		} else if (!strcmp(v[i], "-a")) {
     89 			a->opts->all = true;
     90 		} else if (!strcmp(v[i], "-p")) {
     91 			a->opts->print_number = false;
     92 		} else if (!strcmp(v[i], "-c")) {
     93 			a->opts->count_only = true;
     94 		}
     95 	}
     96 
     97 	if (infinitesols && !fixedmsols)
     98 		a->opts->max_solutions = 1000000; /* 1M = +infty */
     99 
    100 	a->success = (a->scrstdin && i == c) || read_scramble(c-i, &v[i], a);
    101 	return a;
    102 }
    103 
    104 CommandArgs *
    105 gen_parse_args(int c, char **v)
    106 {
    107 	int val;
    108 	CommandArgs *a = new_args();
    109 
    110 	a->opts->nthreads = 64;
    111 	a->success  = false;
    112 
    113 	if (c == 0) {
    114 		a->success = true;
    115 	} else {
    116 		if (!strcmp(v[0], "-t") && c > 1) {
    117 			val = strtol(v[1], NULL, 10);
    118 			if (val < 1 || val > 64) {
    119 				fprintf(stderr,
    120 					"Invalid number of threads."
    121 					"1 <= t <= 64\n");
    122 				return a;
    123 			}
    124 			a->opts->nthreads = val;
    125 			a->success = true;
    126 		}
    127 	}
    128 	
    129 	return a;
    130 }
    131 
    132 CommandArgs *
    133 help_parse_args(int c, char **v)
    134 {
    135 	int i;
    136 	CommandArgs *a = new_args();
    137 
    138 	if (c == 1) {
    139 		for (i = 0; commands[i] != NULL; i++)
    140 			if (!strcmp(v[0], commands[i]->name))
    141 				a->command = commands[i];
    142 		if (a->command == NULL)
    143 			fprintf(stderr, "%s: command not found\n", v[0]);
    144 	}
    145 
    146 	a->success = c == 0 || (c == 1 && a->command != NULL);
    147 	return a;
    148 }
    149 
    150 CommandArgs *
    151 parse_only_scramble(int c, char **v)
    152 {
    153 	CommandArgs *a = new_args();
    154 
    155 	if (!strcmp(v[0], "-i")) {
    156 		a->scrstdin = true;
    157 		a->success = c == 1;
    158 	} else {
    159 		a->success = read_scramble(c, v, a);
    160 	}
    161 
    162 	return a;
    163 }
    164 
    165 CommandArgs *
    166 parse_no_arg(int c, char **v)
    167 {
    168 	CommandArgs *a = new_args();
    169 
    170 	a->success = true;
    171 
    172 	return a;
    173 }
    174 
    175 /* Exec functions implementation *********************************************/
    176 
    177 void
    178 solve_exec(CommandArgs *args)
    179 {
    180 	Cube c;
    181 	AlgList *sols;
    182 	Solver *solver[99];
    183 	Threader *threader;
    184 
    185 	make_solved(&c);
    186 	apply_alg(args->scramble, &c);
    187 /* TODO: adjust */
    188 	threader = &threader_single;
    189 /*	threader = &threader_eager;*/
    190 
    191 /* TODO: adjust */
    192 /* This was to solve steps
    193 	int i;
    194 	for (i = 0; args->cs->step[i] != NULL; i++)
    195 		solver[i] = new_stepsolver_lazy(args->cs->step[i]);
    196 	solver[i] = NULL;
    197 */
    198 
    199 	prepare_solver_nxopt31();
    200 	solver[0] = &solver_nxopt31;
    201 	solver[1] = NULL;
    202 	sols = solve(&c, args->opts, solver, threader);
    203 
    204 	if (args->opts->count_only)
    205 		printf("%d\n", sols->len);
    206 	else
    207 		print_alglist(sols, args->opts->print_number);
    208 
    209 	free_alglist(sols);
    210 }
    211 
    212 void
    213 gen_exec(CommandArgs *args)
    214 {
    215 /* TODO:
    216 	int i;
    217 
    218 	fprintf(stderr, "Generating coordinates...\n");
    219 	fprintf(stderr, "Generating pruning tables...\n");
    220 	for (i = 0; all_pd[i] != NULL; i++)
    221 		genptable(all_pd[i], args->opts->nthreads);
    222 */
    223 
    224 	fprintf(stderr, "Done!\n");
    225 }
    226 
    227 void
    228 help_exec(CommandArgs *args)
    229 {
    230 	if (args->command == NULL) {
    231 		printf(
    232 		       "Use the nissy command \"help COMMAND\" for a short "
    233 		       "description of a specific command.\n"
    234 		       "Use the nissy command \"commands\" for a list of "
    235 		       "available commands.\n"
    236 		       "See the manual page for more details. The manual"
    237 		       " page is available with \"man nissy\" on a UNIX"
    238 		       " system (such as Linux or MacOS) or in pdf and html"
    239 		       " format in the docs folder.\n"
    240 		       "Nissy is available for free at "
    241 		       "https://nissy.tronto.net\n"
    242 		      );
    243 	} else {
    244 		printf("Command %s: %s\nusage: %s\n", args->command->name,
    245 		       args->command->description, args->command->usage);
    246 	}
    247 }
    248 
    249 void
    250 quit_exec(CommandArgs *args)
    251 {
    252 	exit(0);
    253 }
    254 
    255 /* Local functions implementation ********************************************/
    256 
    257 static bool
    258 read_scramble(int c, char **v, CommandArgs *args)
    259 {
    260 	int i, k, n;
    261 	unsigned int j;
    262 	char *algstr;
    263 
    264 	if (c < 1) {
    265 		fprintf(stderr, "Error: no scramble given?\n");
    266 		return false;
    267 	}
    268 
    269 	for(n = 0, i = 0; i < c; i++)
    270 		n += strlen(v[i]);
    271 
    272 	algstr = malloc((n + 1) * sizeof(char));
    273 	k = 0;
    274 	for (i = 0; i < c; i++)
    275 		for (j = 0; j < strlen(v[i]); j++)
    276 			algstr[k++] = v[i][j];
    277 	algstr[k] = 0;
    278 
    279 	args->scramble = new_alg(algstr);
    280 	free(algstr);
    281 
    282 	if (args->scramble->len == 0)
    283 		fprintf(stderr, "Error reading scramble\n");
    284 
    285 	return args->scramble->len > 0;
    286 }
    287 
    288 /* Public functions implementation *******************************************/
    289 
    290 void
    291 free_args(CommandArgs *args)
    292 {
    293 	if (args == NULL)
    294 		return;
    295 
    296 	if (args->scramble != NULL)
    297 		free_alg(args->scramble);
    298 	if (args->opts != NULL)
    299 		free(args->opts);
    300 
    301 	/* step and command must not be freed, they are static! */
    302 
    303 	free(args);
    304 }
    305 
    306 CommandArgs *
    307 new_args()
    308 {
    309 	CommandArgs *args = malloc(sizeof(CommandArgs));
    310 
    311 	args->success = false;
    312 	args->scrstdin = false;
    313 	args->scramble = NULL; /* initialized in read_scramble */
    314 	args->opts = malloc(sizeof(SolveOptions));
    315 
    316 	args->cs = NULL;
    317 	args->command = NULL;
    318 
    319 	return args;
    320 }