diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2025-03-25 14:09:14 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2025-03-25 14:09:14 +0100 |
| commit | 9154476ba6bf400c1eb379f0a3aa6caae2d06d4d (patch) | |
| tree | 73bfb47ccb6cb31a7c91f9917b37a517f2146c24 | |
| parent | cc2dacd43eb7f5ed3a2917612b9a2a9232a61e59 (diff) | |
| download | nissy-core-9154476ba6bf400c1eb379f0a3aa6caae2d06d4d.tar.gz nissy-core-9154476ba6bf400c1eb379f0a3aa6caae2d06d4d.zip | |
Added NISS to coord solver
| -rw-r--r-- | shell/shell.c | 40 | ||||
| -rw-r--r-- | src/core/moves.h | 4 | ||||
| -rw-r--r-- | src/solvers/coord/common.h | 88 | ||||
| -rw-r--r-- | src/solvers/coord/coord.h | 4 | ||||
| -rw-r--r-- | src/solvers/coord/eo.h | 2 | ||||
| -rw-r--r-- | src/solvers/coord/list.h | 4 | ||||
| -rw-r--r-- | src/solvers/coord/solve.h | 199 | ||||
| -rw-r--r-- | src/solvers/coord/types_macros.h | 2 | ||||
| -rw-r--r-- | src/solvers/coord/utils.h | 68 |
9 files changed, 308 insertions, 103 deletions
diff --git a/shell/shell.c b/shell/shell.c index 0387856..1b66f19 100644 --- a/shell/shell.c +++ b/shell/shell.c | |||
| @@ -73,7 +73,8 @@ static int64_t countmoves_exec(args_t *); | |||
| 73 | static int64_t help_exec(args_t *); | 73 | static int64_t help_exec(args_t *); |
| 74 | 74 | ||
| 75 | static int parse_args(int, char **, args_t *); | 75 | static int parse_args(int, char **, args_t *); |
| 76 | static bool parse_uint(char *, unsigned *); | 76 | static bool parse_uint(const char *, unsigned *); |
| 77 | static uint8_t parse_nisstype(const char *); | ||
| 77 | 78 | ||
| 78 | static bool set_cube(int, char **, args_t *); | 79 | static bool set_cube(int, char **, args_t *); |
| 79 | static bool set_cube_perm(int, char **, args_t *); | 80 | static bool set_cube_perm(int, char **, args_t *); |
| @@ -111,7 +112,7 @@ struct { | |||
| 111 | OPTION(FLAG_MOVES, 1, set_str_moves), | 112 | OPTION(FLAG_MOVES, 1, set_str_moves), |
| 112 | OPTION(FLAG_TRANS, 1, set_str_trans), | 113 | OPTION(FLAG_TRANS, 1, set_str_trans), |
| 113 | OPTION(FLAG_SOLVER, 1, set_str_solver), | 114 | OPTION(FLAG_SOLVER, 1, set_str_solver), |
| 114 | OPTION(FLAG_NISSTYPE, 1, set_str_nisstype), /* TODO: more args ? */ | 115 | OPTION(FLAG_NISSTYPE, 1, set_str_nisstype), |
| 115 | OPTION(FLAG_MINMOVES, 1, set_minmoves), | 116 | OPTION(FLAG_MINMOVES, 1, set_minmoves), |
| 116 | OPTION(FLAG_MAXMOVES, 1, set_maxmoves), | 117 | OPTION(FLAG_MAXMOVES, 1, set_maxmoves), |
| 117 | OPTION(FLAG_OPTIMAL, 1, set_optimal), | 118 | OPTION(FLAG_OPTIMAL, 1, set_optimal), |
| @@ -431,12 +432,18 @@ solve_exec(args_t *args) | |||
| 431 | int64_t ret, gendata_ret, size; | 432 | int64_t ret, gendata_ret, size; |
| 432 | size_t read; | 433 | size_t read; |
| 433 | 434 | ||
| 434 | nissflag = NISSY_NISSFLAG_NORMAL; /* TODO: parse str_nisstype */ | 435 | nissflag = parse_nisstype(args->str_nisstype); |
| 436 | if (nissflag == UINT8_MAX) { | ||
| 437 | fprintf(stderr, "solve: unknown niss type '%s', use one " | ||
| 438 | "of the following:\nnormal\ninverse\nlinear\nmixed\nall", | ||
| 439 | args->str_nisstype); | ||
| 440 | return -1; | ||
| 441 | } | ||
| 435 | 442 | ||
| 436 | size = nissy_solverinfo(args->str_solver, dataid); | 443 | size = nissy_solverinfo(args->str_solver, dataid); |
| 437 | 444 | ||
| 438 | if (size < 0) { | 445 | if (size < 0) { |
| 439 | fprintf(stderr, "solve: unknown solver %s\n", | 446 | fprintf(stderr, "solve: unknown solver '%s'\n", |
| 440 | args->str_solver); | 447 | args->str_solver); |
| 441 | return size; | 448 | return size; |
| 442 | } | 449 | } |
| @@ -622,8 +629,8 @@ parse_args(int argc, char **argv, args_t *args) | |||
| 622 | return 0; | 629 | return 0; |
| 623 | } | 630 | } |
| 624 | 631 | ||
| 625 | bool | 632 | static bool |
| 626 | parse_uint(char *argv, unsigned *result) | 633 | parse_uint(const char *argv, unsigned *result) |
| 627 | { | 634 | { |
| 628 | *result = strtol(argv, NULL, 10); | 635 | *result = strtol(argv, NULL, 10); |
| 629 | 636 | ||
| @@ -631,6 +638,27 @@ parse_uint(char *argv, unsigned *result) | |||
| 631 | return true; | 638 | return true; |
| 632 | } | 639 | } |
| 633 | 640 | ||
| 641 | static uint8_t | ||
| 642 | parse_nisstype(const char *arg) | ||
| 643 | { | ||
| 644 | if (!strcmp("normal", arg)) | ||
| 645 | return NISSY_NISSFLAG_NORMAL; | ||
| 646 | |||
| 647 | if (!strcmp("inverse", arg)) | ||
| 648 | return NISSY_NISSFLAG_INVERSE; | ||
| 649 | |||
| 650 | if (!strcmp("linear", arg)) | ||
| 651 | return NISSY_NISSFLAG_LINEAR; | ||
| 652 | |||
| 653 | if (!strcmp("mixed", arg)) | ||
| 654 | return NISSY_NISSFLAG_MIXED; | ||
| 655 | |||
| 656 | if (!strcmp("all", arg)) | ||
| 657 | return NISSY_NISSFLAG_ALL; | ||
| 658 | |||
| 659 | return UINT8_MAX; | ||
| 660 | } | ||
| 661 | |||
| 634 | static bool | 662 | static bool |
| 635 | set_cube(int argc, char **argv, args_t *args) | 663 | set_cube(int argc, char **argv, args_t *args) |
| 636 | { | 664 | { |
diff --git a/src/core/moves.h b/src/core/moves.h index e56d5c8..11ac34e 100644 --- a/src/core/moves.h +++ b/src/core/moves.h | |||
| @@ -15,7 +15,7 @@ STATIC cube_t move(cube_t, uint8_t); | |||
| 15 | STATIC cube_t premove(cube_t, uint8_t); | 15 | STATIC cube_t premove(cube_t, uint8_t); |
| 16 | STATIC uint8_t inverse_move(uint8_t); | 16 | STATIC uint8_t inverse_move(uint8_t); |
| 17 | STATIC void sortparallel_moves(size_t n, uint8_t [n]); | 17 | STATIC void sortparallel_moves(size_t n, uint8_t [n]); |
| 18 | STATIC bool are_lastmoves_singlecw(size_t n, uint8_t [n]); | 18 | STATIC bool are_lastmoves_singlecw(size_t n, const uint8_t [n]); |
| 19 | 19 | ||
| 20 | STATIC cube_t applymoves(cube_t, const char *); | 20 | STATIC cube_t applymoves(cube_t, const char *); |
| 21 | 21 | ||
| @@ -236,7 +236,7 @@ sortparallel_moves(size_t n, uint8_t moves[n]) | |||
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | STATIC bool | 238 | STATIC bool |
| 239 | are_lastmoves_singlecw(size_t n, uint8_t moves[n]) | 239 | are_lastmoves_singlecw(size_t n, const uint8_t moves[n]) |
| 240 | { | 240 | { |
| 241 | bool two; | 241 | bool two; |
| 242 | 242 | ||
diff --git a/src/solvers/coord/common.h b/src/solvers/coord/common.h index 8553658..4cfc36f 100644 --- a/src/solvers/coord/common.h +++ b/src/solvers/coord/common.h | |||
| @@ -1,13 +1,7 @@ | |||
| 1 | coord_t *all_coordinates[] = { | ||
| 2 | &coordinate_eo, | ||
| 3 | NULL | ||
| 4 | }; | ||
| 5 | |||
| 6 | STATIC void append_coord_name(const coord_t *, char *); | 1 | STATIC void append_coord_name(const coord_t *, char *); |
| 7 | STATIC coord_t *parse_coord(size_t n, const char [n]); | 2 | STATIC bool solution_lastqt_cw(const solution_moves_t [static 1]); |
| 8 | STATIC uint8_t parse_axis(size_t n, const char [n]); | 3 | STATIC bool coord_can_switch( |
| 9 | STATIC void parse_coord_and_axis(size_t n, const char [n], coord_t **, uint8_t *); | 4 | const coord_t [static 1], const void *, size_t n, const uint8_t [n]); |
| 10 | STATIC int64_t dataid_coord(const char *, char [static NISSY_DATAID_SIZE]); | ||
| 11 | 5 | ||
| 12 | STATIC void | 6 | STATIC void |
| 13 | append_coord_name(const coord_t *coord, char *str) | 7 | append_coord_name(const coord_t *coord, char *str) |
| @@ -21,66 +15,40 @@ append_coord_name(const coord_t *coord, char *str) | |||
| 21 | str[j] = '\0'; | 15 | str[j] = '\0'; |
| 22 | } | 16 | } |
| 23 | 17 | ||
| 24 | STATIC coord_t * | 18 | STATIC bool |
| 25 | parse_coord(size_t n, const char coord[n]) | 19 | solution_lastqt_cw(const solution_moves_t s[static 1]) |
| 26 | { | 20 | { |
| 27 | int i; | 21 | return are_lastmoves_singlecw(s->nmoves, s->moves) && |
| 28 | 22 | are_lastmoves_singlecw(s->npremoves, s->premoves); | |
| 29 | for (i = 0; all_coordinates[i] != NULL; i++) | ||
| 30 | if (!strncmp(all_coordinates[i]->name, coord, n)) | ||
| 31 | return all_coordinates[i]; | ||
| 32 | |||
| 33 | return NULL; | ||
| 34 | } | ||
| 35 | |||
| 36 | STATIC uint8_t | ||
| 37 | parse_axis(size_t n, const char axis[n]) | ||
| 38 | { | ||
| 39 | if (!strncmp(axis, "UD", n) || !strncmp(axis, "DU", n)) { | ||
| 40 | return AXIS_UD; | ||
| 41 | } else if (!strncmp(axis, "RL", n) || !strncmp(axis, "LR", n)) { | ||
| 42 | return AXIS_RL; | ||
| 43 | } else if (!strncmp(axis, "FB", n) || !strncmp(axis, "BF", n)) { | ||
| 44 | return AXIS_FB; | ||
| 45 | } | ||
| 46 | |||
| 47 | return UINT8_ERROR; | ||
| 48 | } | 23 | } |
| 49 | 24 | ||
| 50 | STATIC void | 25 | STATIC bool |
| 51 | parse_coord_and_axis( | 26 | coord_can_switch( |
| 27 | const coord_t coord[static 1], | ||
| 28 | const void *data, | ||
| 52 | size_t n, | 29 | size_t n, |
| 53 | const char str[n], | 30 | const uint8_t moves[n] |
| 54 | coord_t **coord, | ||
| 55 | uint8_t *axis | ||
| 56 | ) | 31 | ) |
| 57 | { | 32 | { |
| 58 | size_t i; | 33 | /* |
| 59 | 34 | This function checks that the last move (or two moves, if parallel) | |
| 60 | for (i = 0; i < n; i++) | 35 | have a non-trivial effect on the coordinate of the solved cube. This |
| 61 | if (str[i] == '_') | 36 | works in general for all coordinates that have been used so far, but |
| 62 | break; | 37 | in more general cases that have not been considered yet it may fail. |
| 63 | 38 | */ | |
| 64 | if (coord != NULL) | ||
| 65 | *coord = parse_coord(i, str); | ||
| 66 | 39 | ||
| 67 | if (axis != NULL) | 40 | uint64_t i; |
| 68 | *axis = i == n ? UINT8_ERROR : parse_axis(n-i-1, str+i+1); | ||
| 69 | } | ||
| 70 | |||
| 71 | STATIC int64_t | ||
| 72 | dataid_coord(const char *ca, char dataid[static NISSY_DATAID_SIZE]) | ||
| 73 | { | ||
| 74 | coord_t *c; | ||
| 75 | 41 | ||
| 76 | parse_coord_and_axis(strlen(ca), ca, &c, NULL); | 42 | if (n == 0) |
| 43 | return true; | ||
| 77 | 44 | ||
| 78 | if (c == NULL) { | 45 | i = coord->coord(move(SOLVED_CUBE, moves[n-1]), data); |
| 79 | LOG("dataid_coord: cannot parse coordinate from '%s'\n", ca); | 46 | if (i == 0) |
| 80 | return NISSY_ERROR_INVALID_SOLVER; | 47 | return false; |
| 81 | } | ||
| 82 | 48 | ||
| 83 | strcpy(dataid, c->name); | 49 | if (n == 1 || !parallel(moves[n-1], moves[n-2])) |
| 50 | return true; | ||
| 84 | 51 | ||
| 85 | return NISSY_OK; | 52 | i = coord->coord(move(SOLVED_CUBE, moves[n-1]), data); |
| 53 | return i != 0; | ||
| 86 | } | 54 | } |
diff --git a/src/solvers/coord/coord.h b/src/solvers/coord/coord.h index 6ca68c5..f42739d 100644 --- a/src/solvers/coord/coord.h +++ b/src/solvers/coord/coord.h | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | #include "types_macros.h" | 1 | #include "types_macros.h" |
| 2 | #include "eo.h" | ||
| 3 | #include "common.h" | 2 | #include "common.h" |
| 3 | #include "eo.h" | ||
| 4 | #include "list.h" | ||
| 5 | #include "utils.h" | ||
| 4 | #include "gendata.h" | 6 | #include "gendata.h" |
| 5 | #include "solve.h" | 7 | #include "solve.h" |
diff --git a/src/solvers/coord/eo.h b/src/solvers/coord/eo.h index 46a6f70..ef9b27a 100644 --- a/src/solvers/coord/eo.h +++ b/src/solvers/coord/eo.h | |||
| @@ -15,7 +15,7 @@ STATIC coord_t coordinate_eo = { | |||
| 15 | [AXIS_RL] = TRANS_URr, | 15 | [AXIS_RL] = TRANS_URr, |
| 16 | [AXIS_FB] = TRANS_UFr, | 16 | [AXIS_FB] = TRANS_UFr, |
| 17 | }, | 17 | }, |
| 18 | .is_admissible = &are_lastmoves_singlecw, | 18 | .is_admissible = &solution_lastqt_cw, |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | STATIC uint64_t | 21 | STATIC uint64_t |
diff --git a/src/solvers/coord/list.h b/src/solvers/coord/list.h new file mode 100644 index 0000000..32c94a4 --- /dev/null +++ b/src/solvers/coord/list.h | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | coord_t *all_coordinates[] = { | ||
| 2 | &coordinate_eo, | ||
| 3 | NULL | ||
| 4 | }; | ||
diff --git a/src/solvers/coord/solve.h b/src/solvers/coord/solve.h index c056adc..c3fbd02 100644 --- a/src/solvers/coord/solve.h +++ b/src/solvers/coord/solve.h | |||
| @@ -1,66 +1,191 @@ | |||
| 1 | typedef struct { | 1 | typedef struct { |
| 2 | cube_t cube; | 2 | cube_t cube; |
| 3 | cube_t inverse; | ||
| 3 | uint8_t target_depth; | 4 | uint8_t target_depth; |
| 4 | solution_moves_t *solution_moves; | 5 | solution_moves_t *solution_moves; |
| 5 | solution_settings_t *solution_settings; | 6 | solution_settings_t *solution_settings; |
| 7 | solution_list_t *solution_list; | ||
| 8 | uint8_t nissflag; | ||
| 9 | bool lastisnormal; | ||
| 6 | coord_t *coord; | 10 | coord_t *coord; |
| 7 | const void *coord_data; | 11 | const void *coord_data; |
| 8 | const uint8_t *ptable; | 12 | const uint8_t *ptable; |
| 9 | solution_list_t *solution_list; | ||
| 10 | } dfsarg_solve_coord_t; | 13 | } dfsarg_solve_coord_t; |
| 11 | 14 | ||
| 12 | STATIC int64_t solve_coord(cube_t, coord_t *, uint8_t, uint8_t, uint8_t, | 15 | STATIC int64_t solve_coord(cube_t, coord_t [static 1], uint8_t, uint8_t, |
| 13 | uint8_t, uint64_t, int8_t, int, uint64_t, const void *, size_t, char *); | 16 | uint8_t, uint8_t, uint64_t, int8_t, int, uint64_t, const void *, |
| 17 | size_t n, char [n]); | ||
| 14 | STATIC int64_t solve_coord_dispatch(cube_t, const char *, uint8_t, uint8_t, | 18 | STATIC int64_t solve_coord_dispatch(cube_t, const char *, uint8_t, uint8_t, |
| 15 | uint8_t, uint64_t, int8_t, int, uint64_t, const void *, size_t, char *); | 19 | uint8_t, uint64_t, int8_t, int, uint64_t, const void *, size_t n, char [n]); |
| 16 | STATIC int64_t solve_coord_dfs(dfsarg_solve_coord_t *); | 20 | STATIC bool coord_solution_admissible(const dfsarg_solve_coord_t [static 1]); |
| 21 | STATIC bool solve_coord_dfs_stop(const dfsarg_solve_coord_t [static 1]); | ||
| 22 | STATIC bool coord_continue_onnormal(const dfsarg_solve_coord_t [static 1]); | ||
| 23 | STATIC bool coord_continue_oninverse(const dfsarg_solve_coord_t [static 1]); | ||
| 24 | STATIC int64_t solve_coord_dfs(dfsarg_solve_coord_t [static 1]); | ||
| 25 | |||
| 26 | STATIC bool | ||
| 27 | coord_solution_admissible(const dfsarg_solve_coord_t arg[static 1]) | ||
| 28 | { | ||
| 29 | uint8_t n; | ||
| 30 | |||
| 31 | n = arg->solution_moves->nmoves + arg->solution_moves->npremoves; | ||
| 32 | if (arg->target_depth != n) | ||
| 33 | return false; | ||
| 34 | |||
| 35 | return arg->coord->is_admissible == NULL || | ||
| 36 | arg->coord->is_admissible(arg->solution_moves); | ||
| 37 | } | ||
| 38 | |||
| 39 | STATIC bool | ||
| 40 | solve_coord_dfs_stop(const dfsarg_solve_coord_t arg[static 1]) | ||
| 41 | { | ||
| 42 | bool hasnissed; | ||
| 43 | uint8_t n, pval; | ||
| 44 | uint64_t coord; | ||
| 45 | const cube_t *c; | ||
| 46 | |||
| 47 | n = arg->solution_moves->nmoves + arg->solution_moves->npremoves; | ||
| 48 | if (n >= arg->target_depth) | ||
| 49 | return true; | ||
| 50 | |||
| 51 | hasnissed = arg->solution_moves->nmoves > 0 && | ||
| 52 | arg->solution_moves->npremoves > 0; | ||
| 53 | if (!hasnissed && (arg->nissflag & NISSY_NISSFLAG_MIXED)) | ||
| 54 | return false; | ||
| 55 | |||
| 56 | c = arg->lastisnormal ? &arg->cube : &arg->inverse; | ||
| 57 | |||
| 58 | coord = arg->coord->coord(*c, arg->coord_data); | ||
| 59 | pval = get_coord_pval(arg->coord, arg->ptable, coord); | ||
| 60 | |||
| 61 | return n + pval > arg->target_depth; | ||
| 62 | } | ||
| 63 | |||
| 64 | STATIC bool | ||
| 65 | coord_continue_onnormal(const dfsarg_solve_coord_t arg[static 1]) | ||
| 66 | { | ||
| 67 | uint8_t f, nn, ni, th; | ||
| 68 | |||
| 69 | f = arg->nissflag; | ||
| 70 | nn = arg->solution_moves->nmoves; | ||
| 71 | ni = arg->solution_moves->npremoves; | ||
| 72 | th = DIV_ROUND_UP(arg->target_depth, 2); | ||
| 73 | |||
| 74 | if (nn + ni == 0) | ||
| 75 | return f & (NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_MIXED); | ||
| 76 | |||
| 77 | if (arg->lastisnormal) | ||
| 78 | return (f & NISSY_NISSFLAG_NORMAL) || | ||
| 79 | ((f & NISSY_NISSFLAG_MIXED) && (ni > 0 || nn <= th)); | ||
| 80 | |||
| 81 | return (f & NISSY_NISSFLAG_MIXED) && nn == 0 && ni < th && | ||
| 82 | coord_can_switch(arg->coord, arg->coord_data, | ||
| 83 | ni, arg->solution_moves->premoves); | ||
| 84 | } | ||
| 85 | |||
| 86 | STATIC bool | ||
| 87 | coord_continue_oninverse(const dfsarg_solve_coord_t arg[static 1]) | ||
| 88 | { | ||
| 89 | uint8_t f, nn, ni, th; | ||
| 90 | |||
| 91 | f = arg->nissflag; | ||
| 92 | nn = arg->solution_moves->nmoves; | ||
| 93 | ni = arg->solution_moves->npremoves; | ||
| 94 | th = DIV_ROUND_UP(arg->target_depth, 2); | ||
| 95 | |||
| 96 | if (nn + ni == 0) | ||
| 97 | return f & (NISSY_NISSFLAG_INVERSE | NISSY_NISSFLAG_MIXED); | ||
| 98 | |||
| 99 | if (!arg->lastisnormal) | ||
| 100 | return (f & NISSY_NISSFLAG_INVERSE) || | ||
| 101 | ((f & NISSY_NISSFLAG_MIXED) && (nn > 0 || ni < th)); | ||
| 102 | |||
| 103 | return (f & NISSY_NISSFLAG_MIXED) && ni == 0 && nn <= th && | ||
| 104 | coord_can_switch(arg->coord, arg->coord_data, | ||
| 105 | nn, arg->solution_moves->moves); | ||
| 106 | } | ||
| 17 | 107 | ||
| 18 | STATIC int64_t | 108 | STATIC int64_t |
| 19 | solve_coord_dfs(dfsarg_solve_coord_t *arg) | 109 | solve_coord_dfs(dfsarg_solve_coord_t arg[static 1]) |
| 20 | { | 110 | { |
| 21 | uint8_t m, pval; | 111 | bool lastbackup; |
| 112 | uint8_t m, l, nnbackup, nibackup; | ||
| 22 | uint32_t mm; | 113 | uint32_t mm; |
| 23 | uint64_t coord; | 114 | uint64_t coord; |
| 24 | int64_t n, ret; | 115 | int64_t n, ret; |
| 25 | cube_t backup_cube; | 116 | cube_t backup_cube, backup_inverse; |
| 26 | 117 | ||
| 27 | coord = arg->coord->coord(arg->cube, arg->coord_data); | 118 | coord = arg->coord->coord(arg->cube, arg->coord_data); |
| 28 | |||
| 29 | if (coord == 0) { | 119 | if (coord == 0) { |
| 30 | if (arg->solution_moves->nmoves != arg->target_depth || | 120 | if (!coord_solution_admissible(arg)) |
| 31 | (arg->coord->is_admissible != NULL && | ||
| 32 | !arg->coord->is_admissible(arg->solution_moves->nmoves, | ||
| 33 | arg->solution_moves->moves))) | ||
| 34 | return 0; | 121 | return 0; |
| 35 | return appendsolution(arg->solution_moves, | 122 | return appendsolution(arg->solution_moves, |
| 36 | arg->solution_settings, arg->solution_list); | 123 | arg->solution_settings, arg->solution_list); |
| 37 | } | 124 | } |
| 38 | 125 | ||
| 39 | pval = get_coord_pval(arg->coord, arg->ptable, coord); | 126 | if (solve_coord_dfs_stop(arg)) |
| 40 | if (arg->solution_moves->nmoves + pval > arg->target_depth) | ||
| 41 | return 0; | 127 | return 0; |
| 42 | 128 | ||
| 43 | backup_cube = arg->cube; | 129 | backup_cube = arg->cube; |
| 130 | backup_inverse = arg->inverse; | ||
| 131 | lastbackup = arg->lastisnormal; | ||
| 132 | nnbackup = arg->solution_moves->nmoves; | ||
| 133 | nibackup = arg->solution_moves->npremoves; | ||
| 44 | 134 | ||
| 45 | ret = 0; | 135 | ret = 0; |
| 46 | mm = allowednextmove_mask( | 136 | if (coord_continue_onnormal(arg)) { |
| 47 | arg->solution_moves->nmoves, arg->solution_moves->moves); | 137 | l = arg->solution_moves->nmoves; |
| 48 | arg->solution_moves->nmoves++; | 138 | mm = allowednextmove_mask(l, arg->solution_moves->moves); |
| 49 | for (m = 0; m < NMOVES; m++) { | 139 | arg->solution_moves->nmoves++; |
| 50 | if (!(mm & (1 << m))) | 140 | arg->lastisnormal = true; |
| 51 | continue; | ||
| 52 | 141 | ||
| 53 | arg->solution_moves->moves[arg->solution_moves->nmoves-1] = m; | 142 | for (m = 0; m < NMOVES; m++) { |
| 54 | arg->cube = move(backup_cube, m); | 143 | if (!(mm & (UINT32_C(1) << (uint32_t)m))) |
| 55 | n = solve_coord_dfs(arg); | 144 | continue; |
| 56 | if (n < 0) | 145 | |
| 57 | return n; | 146 | arg->solution_moves->moves[l] = m; |
| 58 | ret += n; | 147 | arg->cube = move(backup_cube, m); |
| 148 | arg->inverse = premove(backup_inverse, m); | ||
| 149 | n = solve_coord_dfs(arg); | ||
| 150 | if (n < 0) | ||
| 151 | return n; | ||
| 152 | ret += n; | ||
| 153 | arg->solution_moves->npremoves = nibackup; | ||
| 154 | } | ||
| 155 | |||
| 156 | arg->solution_moves->nmoves--; | ||
| 59 | } | 157 | } |
| 158 | |||
| 159 | arg->lastisnormal = lastbackup; | ||
| 160 | |||
| 161 | if (coord_continue_oninverse(arg)) { | ||
| 162 | l = arg->solution_moves->npremoves; | ||
| 163 | mm = allowednextmove_mask(l, arg->solution_moves->premoves); | ||
| 164 | arg->solution_moves->npremoves++; | ||
| 165 | arg->lastisnormal = false; | ||
| 166 | |||
| 167 | for (m = 0; m < NMOVES; m++) { | ||
| 168 | if (!(mm & (UINT32_C(1) << (uint32_t)m))) | ||
| 169 | continue; | ||
| 170 | |||
| 171 | arg->solution_moves->premoves[l] = m; | ||
| 172 | arg->inverse = move(backup_inverse, m); | ||
| 173 | arg->cube = premove(backup_cube, m); | ||
| 174 | n = solve_coord_dfs(arg); | ||
| 175 | if (n < 0) | ||
| 176 | return n; | ||
| 177 | ret += n; | ||
| 178 | arg->solution_moves->nmoves = nnbackup; | ||
| 179 | } | ||
| 180 | |||
| 181 | arg->solution_moves->npremoves--; | ||
| 182 | } | ||
| 183 | |||
| 60 | arg->cube = backup_cube; | 184 | arg->cube = backup_cube; |
| 61 | arg->solution_moves->nmoves--; | 185 | arg->inverse = backup_inverse; |
| 186 | arg->lastisnormal = lastbackup; | ||
| 62 | 187 | ||
| 63 | return 0; | 188 | return ret; |
| 64 | } | 189 | } |
| 65 | 190 | ||
| 66 | STATIC int64_t | 191 | STATIC int64_t |
| @@ -76,7 +201,7 @@ solve_coord_dispatch( | |||
| 76 | uint64_t data_size, | 201 | uint64_t data_size, |
| 77 | const void *data, | 202 | const void *data, |
| 78 | size_t solutions_size, | 203 | size_t solutions_size, |
| 79 | char *sols | 204 | char sols[solutions_size] |
| 80 | ) | 205 | ) |
| 81 | { | 206 | { |
| 82 | coord_t *coord; | 207 | coord_t *coord; |
| @@ -103,7 +228,7 @@ solve_coord_dispatch( | |||
| 103 | STATIC int64_t | 228 | STATIC int64_t |
| 104 | solve_coord( | 229 | solve_coord( |
| 105 | cube_t cube, | 230 | cube_t cube, |
| 106 | coord_t *coord, | 231 | coord_t coord [static 1], |
| 107 | uint8_t axis, | 232 | uint8_t axis, |
| 108 | uint8_t nissflag, | 233 | uint8_t nissflag, |
| 109 | uint8_t minmoves, | 234 | uint8_t minmoves, |
| @@ -114,7 +239,7 @@ solve_coord( | |||
| 114 | uint64_t data_size, | 239 | uint64_t data_size, |
| 115 | const void *data, | 240 | const void *data, |
| 116 | size_t solutions_size, | 241 | size_t solutions_size, |
| 117 | char *sols | 242 | char sols[solutions_size] |
| 118 | ) | 243 | ) |
| 119 | { | 244 | { |
| 120 | int8_t d; | 245 | int8_t d; |
| @@ -160,12 +285,22 @@ solve_coord( | |||
| 160 | 285 | ||
| 161 | arg = (dfsarg_solve_coord_t) { | 286 | arg = (dfsarg_solve_coord_t) { |
| 162 | .cube = c, | 287 | .cube = c, |
| 288 | .inverse = inverse(c), | ||
| 163 | .coord = coord, | 289 | .coord = coord, |
| 164 | .coord_data = coord_data, | 290 | .coord_data = coord_data, |
| 165 | .ptable = ptable, | 291 | .ptable = ptable, |
| 166 | .solution_moves = &solution_moves, | 292 | .solution_moves = &solution_moves, |
| 167 | .solution_settings = &solution_settings, | 293 | .solution_settings = &solution_settings, |
| 168 | .solution_list = &solution_list, | 294 | .solution_list = &solution_list, |
| 295 | .nissflag = nissflag, | ||
| 296 | |||
| 297 | /* | ||
| 298 | Since no move has been done yet, this field should be | ||
| 299 | neither true nor false; using its value now is logically | ||
| 300 | undefined behavior. | ||
| 301 | TODO: find a more elegant solution | ||
| 302 | */ | ||
| 303 | .lastisnormal = true, | ||
| 169 | }; | 304 | }; |
| 170 | 305 | ||
| 171 | if (coord->coord(c, coord_data) == 0) { | 306 | if (coord->coord(c, coord_data) == 0) { |
diff --git a/src/solvers/coord/types_macros.h b/src/solvers/coord/types_macros.h index f2d436c..9eaeca0 100644 --- a/src/solvers/coord/types_macros.h +++ b/src/solvers/coord/types_macros.h | |||
| @@ -11,5 +11,5 @@ typedef struct { | |||
| 11 | uint32_t moves_mask; | 11 | uint32_t moves_mask; |
| 12 | uint64_t trans_mask; | 12 | uint64_t trans_mask; |
| 13 | uint8_t axistrans[3]; | 13 | uint8_t axistrans[3]; |
| 14 | bool (*is_admissible)(size_t n, uint8_t [n]); | 14 | bool (*is_admissible)(const solution_moves_t[static 1]); |
| 15 | } coord_t; | 15 | } coord_t; |
diff --git a/src/solvers/coord/utils.h b/src/solvers/coord/utils.h new file mode 100644 index 0000000..ab4aded --- /dev/null +++ b/src/solvers/coord/utils.h | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | STATIC coord_t *parse_coord(size_t n, const char [n]); | ||
| 2 | STATIC uint8_t parse_axis(size_t n, const char [n]); | ||
| 3 | STATIC void parse_coord_and_axis(size_t n, const char [n], coord_t **, uint8_t *); | ||
| 4 | STATIC int64_t dataid_coord(const char *, char [static NISSY_DATAID_SIZE]); | ||
| 5 | |||
| 6 | STATIC coord_t * | ||
| 7 | parse_coord(size_t n, const char coord[n]) | ||
| 8 | { | ||
| 9 | int i; | ||
| 10 | |||
| 11 | for (i = 0; all_coordinates[i] != NULL; i++) | ||
| 12 | if (!strncmp(all_coordinates[i]->name, coord, n)) | ||
| 13 | return all_coordinates[i]; | ||
| 14 | |||
| 15 | return NULL; | ||
| 16 | } | ||
| 17 | |||
| 18 | STATIC uint8_t | ||
| 19 | parse_axis(size_t n, const char axis[n]) | ||
| 20 | { | ||
| 21 | if (!strncmp(axis, "UD", n) || !strncmp(axis, "DU", n)) { | ||
| 22 | return AXIS_UD; | ||
| 23 | } else if (!strncmp(axis, "RL", n) || !strncmp(axis, "LR", n)) { | ||
| 24 | return AXIS_RL; | ||
| 25 | } else if (!strncmp(axis, "FB", n) || !strncmp(axis, "BF", n)) { | ||
| 26 | return AXIS_FB; | ||
| 27 | } | ||
| 28 | |||
| 29 | return UINT8_ERROR; | ||
| 30 | } | ||
| 31 | |||
| 32 | STATIC void | ||
| 33 | parse_coord_and_axis( | ||
| 34 | size_t n, | ||
| 35 | const char str[n], | ||
| 36 | coord_t **coord, | ||
| 37 | uint8_t *axis | ||
| 38 | ) | ||
| 39 | { | ||
| 40 | size_t i; | ||
| 41 | |||
| 42 | for (i = 0; i < n; i++) | ||
| 43 | if (str[i] == '_') | ||
| 44 | break; | ||
| 45 | |||
| 46 | if (coord != NULL) | ||
| 47 | *coord = parse_coord(i, str); | ||
| 48 | |||
| 49 | if (axis != NULL) | ||
| 50 | *axis = i == n ? UINT8_ERROR : parse_axis(n-i-1, str+i+1); | ||
| 51 | } | ||
| 52 | |||
| 53 | STATIC int64_t | ||
| 54 | dataid_coord(const char *ca, char dataid[static NISSY_DATAID_SIZE]) | ||
| 55 | { | ||
| 56 | coord_t *c; | ||
| 57 | |||
| 58 | parse_coord_and_axis(strlen(ca), ca, &c, NULL); | ||
| 59 | |||
| 60 | if (c == NULL) { | ||
| 61 | LOG("dataid_coord: cannot parse coordinate from '%s'\n", ca); | ||
| 62 | return NISSY_ERROR_INVALID_SOLVER; | ||
| 63 | } | ||
| 64 | |||
| 65 | strcpy(dataid, c->name); | ||
| 66 | |||
| 67 | return NISSY_OK; | ||
| 68 | } | ||
