From 6f4313bc1ed5be794146e6ca2fd73f48c7906061 Mon Sep 17 00:00:00 2001 From: Sebastiano Tronto Date: Mon, 1 May 2023 12:48:55 +0200 Subject: Reverted to 2.0.3 --- src/commands.c | 358 +++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 271 insertions(+), 87 deletions(-) (limited to 'src/commands.c') diff --git a/src/commands.c b/src/commands.c index a9e8fc9..4d3ad50 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1,11 +1,187 @@ -#define COMMANDS_C - #include "commands.h" -static bool read_cs(CommandArgs *args, char *str); +/* Arg parsing functions *****************************************************/ + +CommandArgs * gen_parse_args(int c, char **v); +CommandArgs * help_parse_args(int c, char **v); +CommandArgs * parse_only_scramble(int c, char **v); +CommandArgs * parse_no_arg(int c, char **v); +CommandArgs * solve_parse_args(int c, char **v); +CommandArgs * scramble_parse_args(int c, char **v); + +/* Exec functions ************************************************************/ + +static void gen_exec(CommandArgs *args); +static void cleanup_exec(CommandArgs *args); +static void invert_exec(CommandArgs *args); +static void solve_exec(CommandArgs *args); +static void scramble_exec(CommandArgs *args); +static void steps_exec(CommandArgs *args); +static void commands_exec(CommandArgs *args); +static void freemem_exec(CommandArgs *args); +static void print_exec(CommandArgs *args); +static void twophase_exec(CommandArgs *args); +static void help_exec(CommandArgs *args); +static void quit_exec(CommandArgs *args); +static void unniss_exec(CommandArgs *args); +static void version_exec(CommandArgs *args); + +/* Local functions ***********************************************************/ + +static bool read_step(CommandArgs *args, char *str); static bool read_scrtype(CommandArgs *args, char *str); static bool read_scramble(int c, char **v, CommandArgs *args); +/* Commands ******************************************************************/ + +Command +solve_cmd = { + .name = "solve", + .usage = "solve STEP [OPTIONS] SCRAMBLE", + .description = "Solve a step; see command steps for a list of steps", + .parse_args = solve_parse_args, + .exec = solve_exec +}; + +Command +scramble_cmd = { + .name = "scramble", + .usage = "scramble [TYPE] [-n N]", + .description = "Get a random-position scramble", + .parse_args = scramble_parse_args, + .exec = scramble_exec, +}; + +Command +gen_cmd = { + .name = "gen", + .usage = "gen [-t N]", + .description = "Generate all tables [using N threads]", + .parse_args = gen_parse_args, + .exec = gen_exec +}; + +Command +invert_cmd = { + .name = "invert", + .usage = "invert SCRAMBLE]", + .description = "Invert a scramble", + .parse_args = parse_only_scramble, + .exec = invert_exec, +}; + +Command +steps_cmd = { + .name = "steps", + .usage = "steps", + .description = "List available steps", + .parse_args = parse_no_arg, + .exec = steps_exec +}; + +Command +commands_cmd = { + .name = "commands", + .usage = "commands", + .description = "List available commands", + .parse_args = parse_no_arg, + .exec = commands_exec +}; + +Command +freemem_cmd = { + .name = "freemem", + .usage = "freemem", + .description = "free large tables from RAM", + .parse_args = parse_no_arg, + .exec = freemem_exec, +}; + +Command +print_cmd = { + .name = "print", + .usage = "print SCRAMBLE", + .description = "Print written description of the cube", + .parse_args = parse_only_scramble, + .exec = print_exec, +}; + +Command +help_cmd = { + .name = "help", + .usage = "help [COMMAND]", + .description = "Display nissy manual page or help on specific command", + .parse_args = help_parse_args, + .exec = help_exec, +}; + +Command +twophase_cmd = { + .name = "twophase", + .usage = "twophase", + .description = "Find a solution quickly using a 2-phase method", + .parse_args = parse_only_scramble, + .exec = twophase_exec, +}; + +Command +quit_cmd = { + .name = "quit", + .usage = "quit", + .description = "Quit nissy", + .parse_args = parse_no_arg, + .exec = quit_exec, +}; + +Command +cleanup_cmd = { + .name = "cleanup", + .usage = "cleanup SCRAMBLE", + .description = "Rewrite a scramble using only standard moves (HTM)", + .parse_args = parse_only_scramble, + .exec = cleanup_exec, +}; + +Command +unniss_cmd = { + .name = "unniss", + .usage = "unniss SCRAMBLE", + .description = "Rewrite a scramble without NISS", + .parse_args = parse_only_scramble, + .exec = unniss_exec, +}; + +Command +version_cmd = { + .name = "version", + .usage = "version", + .description = "print nissy version", + .parse_args = parse_no_arg, + .exec = version_exec, +}; + +Command *commands[] = { + &commands_cmd, + &freemem_cmd, + &gen_cmd, + &help_cmd, + &invert_cmd, + &print_cmd, + &quit_cmd, + &solve_cmd, + &scramble_cmd, + &steps_cmd, + &twophase_cmd, + &cleanup_cmd, + &unniss_cmd, + &version_cmd, + NULL +}; + +/* Other constants ***********************************************************/ + +char *scrtypes[20] = { "eo", "corners", "edges", "fmc", "dr", "htr", NULL }; + /* Arg parsing functions implementation **************************************/ CommandArgs * @@ -95,7 +271,7 @@ solve_parse_args(int c, char **v) a->opts->print_number = false; } else if (!strcmp(v[i], "-c")) { a->opts->count_only = true; - } else if (!read_cs(a, v[i])) { + } else if (!read_step(a, v[i])) { break; } } @@ -210,26 +386,17 @@ parse_no_arg(int c, char **v) /* Exec functions implementation *********************************************/ -void +static void solve_exec(CommandArgs *args) { Cube c; AlgList *sols; - Solver *solver[99]; - Threader *threader; - make_solved(&c); - apply_alg(args->scramble, &c); -/* TODO: adjust */ -/* threader = &threader_single;*/ - threader = &threader_eager; + init_all_movesets(); + init_symcoord(); -/* TODO: adjust */ - int i; - for (i = 0; args->cs->step[i] != NULL; i++) - solver[i] = new_stepsolver_lazy(args->cs->step[i]); - solver[i] = NULL; - sols = solve(&c, args->opts, solver, threader); + c = apply_alg(args->scramble, (Cube){0}); + sols = solve(c, args->step, args->opts); if (args->opts->count_only) printf("%d\n", sols->len); @@ -239,67 +406,85 @@ solve_exec(CommandArgs *args) free_alglist(sols); } -void +static void scramble_exec(CommandArgs *args) { Cube cube; + CubeArray *arr; Alg *scr, *ruf, *aux; - int i, j, eo, ep, co, cp; + int i, j, eo, ep, co, cp, a[12]; + int eparr[12] = { [8] = 8, [9] = 9, [10] = 10, [11] = 11 }; uint64_t ui, uj, uk; + init_all_movesets(); + init_symcoord(); + srand(time(NULL)); for (i = 0; i < args->n; i++) { if (!strcmp(args->scrtype, "dr")) { - ui = rand() % FACTORIAL8; - uj = rand() % FACTORIAL8; - uk = rand() % FACTORIAL4; - - make_solved(&cube); - index_to_perm(ui, 8, cube.cp); - index_to_perm(uj, 8, cube.ep); - index_to_perm(uk, 4, cube.ep + 8); - for (j = 8; j < 12; j++) - cube.ep[j] += 8; + /* Warning: cube is inconsistent because of side CO * + * and EO on U/D. But solve_2phase only solves drfin * + * in this case, so it should be ok. * + * TODO: check this properly * + * Moreover we again need to fix parity after * + * generating epose manually */ + do { + ui = rand() % FACTORIAL8; + uj = rand() % FACTORIAL8; + uk = rand() % FACTORIAL4; + + index_to_perm(ui, 8, eparr); + arr = malloc(sizeof(CubeArray)); + arr->ep = eparr; + cube = arrays_to_cube(arr, pf_ep); + free(arr); + + cube.cp = uj; + cube.epose = uk; + } while (!is_admissible(cube)); } else if (!strcmp(args->scrtype, "htr")) { - make_solved(&cube); - /* TODO */ + /* antindex_htrfin() returns a consistent * + * cube, except possibly for parity */ + do { + ui = rand() % (24*24/6); + cube = (Cube){0}; + cube.cp = cornershtrfin_ant[ui]; + cube.epose = rand() % 24; + cube.eposs = rand() % 24; + cube.eposm = rand() % 24; + } while (!is_admissible(cube)); } else { - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; eo = rand() % POW2TO11; + ep = rand() % FACTORIAL12; co = rand() % POW3TO7; + cp = rand() % FACTORIAL8; if (!strcmp(args->scrtype, "eo")) { eo = 0; } else if (!strcmp(args->scrtype, "corners")) { eo = 0; ep = 0; + index_to_perm(cp, 8, a); + if (perm_sign(a, 8) == 1) { + swap(&a[0], &a[1]); + cp = perm_to_index(a, 8); + } } else if (!strcmp(args->scrtype, "edges")) { co = 0; cp = 0; + index_to_perm(ep, 12, a); + if (perm_sign(a, 12) == 1) { + swap(&a[0], &a[1]); + ep = perm_to_index(a, 12); + } } - - make_solved(&cube); - index_to_perm(ep, 12, cube.ep); - index_to_perm(cp, 8, cube.cp); - int_to_sum_zero_array(eo, 2, 12, cube.eo); - int_to_sum_zero_array(co, 3, 8, cube.co); - } - - if (!is_admissible(&cube)) { - if (!strcmp(args->scrtype, "corners")) - swap(&cube.cp[UFR], &cube.cp[UFL]); - else - swap(&cube.ep[UF], &cube.ep[UB]); + cube = fourval_to_cube(eo, ep, co, cp); } /* TODO: can be optimized for htr and dr using htrfin, drfin */ - /* - TODO: solve_2phase was removed - scr = solve_2phase(&cube, 1); - */ + scr = solve_2phase(cube, 1); if (!strcmp(args->scrtype, "fmc")) { aux = new_alg(""); @@ -328,22 +513,23 @@ scramble_exec(CommandArgs *args) } } -void +static void gen_exec(CommandArgs *args) { -/* TODO: int i; fprintf(stderr, "Generating coordinates...\n"); + init_all_movesets(); + init_symcoord(); + fprintf(stderr, "Generating pruning tables...\n"); for (i = 0; all_pd[i] != NULL; i++) genptable(all_pd[i], args->opts->nthreads); -*/ fprintf(stderr, "Done!\n"); } -void +static void invert_exec(CommandArgs *args) { Alg *inv; @@ -354,16 +540,16 @@ invert_exec(CommandArgs *args) free_alg(inv); } -void +static void steps_exec(CommandArgs *args) { int i; - for (i = 0; csteps[i] != NULL; i++) - printf("%-15s %s\n", csteps[i]->shortname, csteps[i]->name); + for (i = 0; steps[i] != NULL; i++) + printf("%-15s %s\n", steps[i]->shortname, steps[i]->name); } -void +static void commands_exec(CommandArgs *args) { int i; @@ -373,10 +559,9 @@ commands_exec(CommandArgs *args) } -void +static void freemem_exec(CommandArgs *args) { -/* TODO: int i; for (i = 0; all_pd[i] != NULL; i++) @@ -384,36 +569,35 @@ freemem_exec(CommandArgs *args) for (i = 0; all_sd[i] != NULL; i++) free_sd(all_sd[i]); -*/ + + /* TODO: invtables are also large, but for now they are * + * statically allocated. Consider releasing those too. */ } -void +static void print_exec(CommandArgs *args) { - Cube c; - - make_solved(&c); - apply_alg(args->scramble, &c); - print_cube(&c); + init_moves(); + print_cube(apply_alg(args->scramble, (Cube){0})); } -/* -void +static void twophase_exec(CommandArgs *args) { Cube c; Alg *sol; - make_solved(&c); - apply_alg(args->scramble, &c); - sol = solve_2phase(&c, 1); + init_all_movesets(); + init_symcoord(); + + c = apply_alg(args->scramble, (Cube){0}); + sol = solve_2phase(c, 1); print_alg(sol, false); free_alg(sol); } -*/ -void +static void help_exec(CommandArgs *args) { if (args->command == NULL) { @@ -427,7 +611,7 @@ help_exec(CommandArgs *args) " system (such as Linux or MacOS) or in pdf and html" " format in the docs folder.\n" "Nissy is available for free at " - "https://nissy.tronto.net\n" + "https://github.com/sebastianotronto/nissy\n" ); } else { printf("Command %s: %s\nusage: %s\n", args->command->name, @@ -435,24 +619,26 @@ help_exec(CommandArgs *args) } } -void +static void quit_exec(CommandArgs *args) { exit(0); } -void +static void cleanup_exec(CommandArgs *args) { Alg *alg; + init_moves(); + alg = cleanup(args->scramble); print_alg(alg, false); free_alg(alg); } -void +static void unniss_exec(CommandArgs *args) { Alg *aux; @@ -462,7 +648,7 @@ unniss_exec(CommandArgs *args) free(aux); } -void +static void version_exec(CommandArgs *args) { printf(VERSION"\n"); @@ -505,8 +691,6 @@ static bool read_scrtype(CommandArgs *args, char *str) { int i; - static char *scrtypes[20] = - { "eo", "corners", "edges", "fmc", "dr", "htr", NULL }; for (i = 0; scrtypes[i] != NULL; i++) { if (!strcmp(scrtypes[i], str)) { @@ -519,13 +703,13 @@ read_scrtype(CommandArgs *args, char *str) } static bool -read_cs(CommandArgs *args, char *str) +read_step(CommandArgs *args, char *str) { int i; - for (i = 0; csteps[i] != NULL; i++) { - if (!strcmp(csteps[i]->shortname, str)) { - args->cs = csteps[i]; + for (i = 0; steps[i] != NULL; i++) { + if (!strcmp(steps[i]->shortname, str)) { + args->step = steps[i]; return true; } } @@ -562,7 +746,7 @@ new_args() args->opts = malloc(sizeof(SolveOptions)); /* step and command are static */ - args->cs = csteps[0]; /* default: first step in list */ + args->step = steps[0]; /* default: first step in list */ args->command = NULL; return args; -- cgit v1.3