diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | TODO.md | 1 | ||||
| -rwxr-xr-x | nissy | bin | 0 -> 188520 bytes | |||
| -rw-r--r-- | nissy-2.0beta7.tar.gz | bin | 0 -> 58162 bytes | |||
| -rwxr-xr-x | nissy.exe | bin | 646402 -> 653654 bytes | |||
| -rw-r--r-- | src/alg.c | 32 | ||||
| -rw-r--r-- | src/alg.h | 2 | ||||
| -rw-r--r-- | src/cubetypes.h | 32 | ||||
| -rw-r--r-- | src/solve.c | 314 | ||||
| -rw-r--r-- | src/steps.c | 499 | ||||
| -rw-r--r-- | src/steps.h | 8 | ||||
| -rw-r--r-- | src/utils.c | 14 | ||||
| -rw-r--r-- | src/utils.h | 2 |
13 files changed, 618 insertions, 288 deletions
| @@ -1,6 +1,6 @@ | |||
| 1 | # See LICENSE file for copyright and license details. | 1 | # See LICENSE file for copyright and license details. |
| 2 | 2 | ||
| 3 | VERSION = 2.0beta6 | 3 | VERSION = 2.0beta7 |
| 4 | 4 | ||
| 5 | PREFIX = /usr/local | 5 | PREFIX = /usr/local |
| 6 | MANPREFIX = ${PREFIX}/share/man | 6 | MANPREFIX = ${PREFIX}/share/man |
| @@ -28,6 +28,7 @@ It's more of a personal reminder than anything else. | |||
| 28 | * solve should try up to a small bound without loading the large pruning table | 28 | * solve should try up to a small bound without loading the large pruning table |
| 29 | * drfin for HTR scrambles should try all 3 axis and pick the best solutions; | 29 | * drfin for HTR scrambles should try all 3 axis and pick the best solutions; |
| 30 | in general every step that automatically detects orientation should do this | 30 | in general every step that automatically detects orientation should do this |
| 31 | * for solve -v, print certain info like average branching value | ||
| 31 | 32 | ||
| 32 | ### New features | 33 | ### New features |
| 33 | * cleanup: translate an alg to the standard HTM moveset + reorient at the end | 34 | * cleanup: translate an alg to the standard HTM moveset + reorient at the end |
| Binary files differ | |||
diff --git a/nissy-2.0beta7.tar.gz b/nissy-2.0beta7.tar.gz new file mode 100644 index 0000000..578e4ab --- /dev/null +++ b/nissy-2.0beta7.tar.gz | |||
| Binary files differ | |||
| Binary files differ | |||
| @@ -373,3 +373,35 @@ realloc_alg(Alg *alg, int n) | |||
| 373 | alg->allocated = n; | 373 | alg->allocated = n; |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | void | ||
| 377 | swapmove(Move *m1, Move *m2) | ||
| 378 | { | ||
| 379 | Move aux; | ||
| 380 | |||
| 381 | aux = *m1; | ||
| 382 | *m1 = *m2; | ||
| 383 | *m2 = aux; | ||
| 384 | } | ||
| 385 | |||
| 386 | void | ||
| 387 | unniss(Alg *alg) | ||
| 388 | { | ||
| 389 | int i; | ||
| 390 | Alg *aux; | ||
| 391 | |||
| 392 | aux = new_alg(""); | ||
| 393 | |||
| 394 | for (i = 0; i < alg->len; i++) | ||
| 395 | if (!alg->inv[i]) | ||
| 396 | append_move(aux, alg->move[i], false); | ||
| 397 | |||
| 398 | for (i = alg->len-1; i >= 0; i--) | ||
| 399 | if (alg->inv[i]) | ||
| 400 | append_move(aux, inverse_move(alg->move[i]), false); | ||
| 401 | |||
| 402 | for (i = 0; i < alg->len; i++) { | ||
| 403 | alg->move[i] = aux->move[i]; | ||
| 404 | alg->inv[i] = false; | ||
| 405 | } | ||
| 406 | free(aux); | ||
| 407 | } | ||
| @@ -30,6 +30,8 @@ AlgList * new_alglist(); | |||
| 30 | Alg * on_inverse(Alg *alg); | 30 | Alg * on_inverse(Alg *alg); |
| 31 | void print_alg(Alg *alg, bool l); | 31 | void print_alg(Alg *alg, bool l); |
| 32 | void print_alglist(AlgList *al, bool l); | 32 | void print_alglist(AlgList *al, bool l); |
| 33 | void swapmove(Move *m1, Move *m2); | ||
| 34 | void unniss(Alg *alg); | ||
| 33 | 35 | ||
| 34 | #endif | 36 | #endif |
| 35 | 37 | ||
diff --git a/src/cubetypes.h b/src/cubetypes.h index 9ec8620..3ad960b 100644 --- a/src/cubetypes.h +++ b/src/cubetypes.h | |||
| @@ -81,9 +81,8 @@ typedef struct commandargs CommandArgs; | |||
| 81 | typedef struct coordinate Coordinate; | 81 | typedef struct coordinate Coordinate; |
| 82 | typedef struct cube Cube; | 82 | typedef struct cube Cube; |
| 83 | typedef struct cubearray CubeArray; | 83 | typedef struct cubearray CubeArray; |
| 84 | typedef struct dfsdata DfsData; | 84 | typedef struct dfsarg DfsArg; |
| 85 | typedef struct estimatedata EstimateData; | 85 | typedef struct estimatedata EstimateData; |
| 86 | typedef struct localinfo LocalInfo; | ||
| 87 | typedef struct piecefilter PieceFilter; | 86 | typedef struct piecefilter PieceFilter; |
| 88 | typedef struct prunedata PruneData; | 87 | typedef struct prunedata PruneData; |
| 89 | typedef struct solveoptions SolveOptions; | 88 | typedef struct solveoptions SolveOptions; |
| @@ -94,7 +93,7 @@ typedef struct threaddatagenpt ThreadDataGenpt; | |||
| 94 | 93 | ||
| 95 | typedef Cube (*AntiIndexer) (uint64_t); | 94 | typedef Cube (*AntiIndexer) (uint64_t); |
| 96 | typedef bool (*Checker) (Cube); | 95 | typedef bool (*Checker) (Cube); |
| 97 | typedef int (*Estimator) (EstimateData *); | 96 | typedef int (*Estimator) (DfsArg *); |
| 98 | typedef bool (*Validator) (Alg *); | 97 | typedef bool (*Validator) (Alg *); |
| 99 | typedef void (*Exec) (CommandArgs *); | 98 | typedef void (*Exec) (CommandArgs *); |
| 100 | typedef uint64_t (*Indexer) (Cube); | 99 | typedef uint64_t (*Indexer) (Cube); |
| @@ -198,36 +197,31 @@ cubearray | |||
| 198 | }; | 197 | }; |
| 199 | 198 | ||
| 200 | struct | 199 | struct |
| 201 | dfsdata | 200 | dfsarg |
| 202 | { | 201 | { |
| 202 | Step * step; | ||
| 203 | SolveOptions * opts; | ||
| 204 | Cube cube; | ||
| 205 | Cube inverse; | ||
| 203 | int d; | 206 | int d; |
| 204 | int m; | 207 | uint64_t badmoves; |
| 205 | int lb; | 208 | uint64_t badmovesinv; |
| 206 | bool niss; | 209 | bool niss; |
| 207 | Move last1; | 210 | Move last1; |
| 208 | Move last2; | 211 | Move last2; |
| 212 | Move last1inv; | ||
| 213 | Move last2inv; | ||
| 209 | EstimateData * ed; | 214 | EstimateData * ed; |
| 210 | AlgList * sols; | 215 | AlgList * sols; |
| 211 | pthread_mutex_t * sols_mutex; | 216 | pthread_mutex_t * sols_mutex; |
| 212 | Alg * current_alg; | 217 | Alg * current_alg; |
| 213 | Move * sorted_moves; | 218 | Move * sorted_moves; |
| 214 | int * move_position; | 219 | int * move_position; |
| 215 | uint8_t * visited; | ||
| 216 | }; | 220 | }; |
| 217 | 221 | ||
| 218 | struct | 222 | struct |
| 219 | estimatedata | 223 | estimatedata |
| 220 | { | 224 | { |
| 221 | Cube cube; | ||
| 222 | int target; | ||
| 223 | Move lastmove; | ||
| 224 | uint64_t movebitmask; | ||
| 225 | LocalInfo * li; | ||
| 226 | }; | ||
| 227 | |||
| 228 | struct | ||
| 229 | localinfo | ||
| 230 | { | ||
| 231 | int corners; | 225 | int corners; |
| 232 | int normal_ud; | 226 | int normal_ud; |
| 233 | int normal_fb; | 227 | int normal_fb; |
| @@ -235,7 +229,7 @@ localinfo | |||
| 235 | int inverse_ud; | 229 | int inverse_ud; |
| 236 | int inverse_fb; | 230 | int inverse_fb; |
| 237 | int inverse_rl; | 231 | int inverse_rl; |
| 238 | int prev_ret; | 232 | int oldret; |
| 239 | }; | 233 | }; |
| 240 | 234 | ||
| 241 | struct | 235 | struct |
| @@ -284,6 +278,8 @@ step | |||
| 284 | { | 278 | { |
| 285 | char * shortname; | 279 | char * shortname; |
| 286 | char * name; | 280 | char * name; |
| 281 | bool final; | ||
| 282 | Checker is_done; | ||
| 287 | Estimator estimate; | 283 | Estimator estimate; |
| 288 | Checker ready; | 284 | Checker ready; |
| 289 | char * ready_msg; | 285 | char * ready_msg; |
diff --git a/src/solve.c b/src/solve.c index ec16935..ea3b7ae 100644 --- a/src/solve.c +++ b/src/solve.c | |||
| @@ -2,155 +2,208 @@ | |||
| 2 | 2 | ||
| 3 | /* Local functions ***********************************************************/ | 3 | /* Local functions ***********************************************************/ |
| 4 | 4 | ||
| 5 | static bool allowed_next(Move move, DfsData *dd, uint64_t mm); | 5 | static bool allowed_next(Move move, DfsArg *arg); |
| 6 | static void dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd); | 6 | static bool cancel_niss(DfsArg *arg); |
| 7 | static void dfs_branch(Cube c, Step *s, SolveOptions *os, DfsData *dd); | 7 | static void copy_dfsarg(DfsArg *src, DfsArg *dst); |
| 8 | static bool dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd); | 8 | static void dfs(DfsArg *arg); |
| 9 | static void dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd); | 9 | static void dfs_branch(DfsArg *arg); |
| 10 | static bool dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd); | 10 | static bool dfs_check_solved(DfsArg *arg); |
| 11 | static bool dfs_switch_final(DfsArg *arg); | ||
| 12 | static void dfs_niss(DfsArg *arg); | ||
| 13 | static bool dfs_stop(DfsArg *arg); | ||
| 11 | static void * instance_thread(void *arg); | 14 | static void * instance_thread(void *arg); |
| 15 | static void invert_branch(DfsArg *arg); | ||
| 12 | static void multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d); | 16 | static void multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d); |
| 17 | static bool niss_makes_sense(DfsArg *arg); | ||
| 13 | 18 | ||
| 14 | /* Local functions ***********************************************************/ | 19 | /* Local functions ***********************************************************/ |
| 15 | 20 | ||
| 16 | static bool | 21 | static bool |
| 17 | allowed_next(Move move, DfsData *dd, uint64_t mm) | 22 | allowed_next(Move m, DfsArg *arg) |
| 18 | { | 23 | { |
| 19 | if ((1 << move) & mm) | 24 | if ((1 << m) & arg->badmoves) |
| 20 | return false; | 25 | return false; |
| 21 | 26 | ||
| 22 | if (!possible_next(dd->last2, dd->last1, move)) | 27 | if (!possible_next(arg->last2, arg->last1, m)) |
| 23 | return false; | 28 | return false; |
| 24 | 29 | ||
| 25 | if (commute(dd->last1, move)) | 30 | if (commute(arg->last1, m)) |
| 26 | return dd->move_position[dd->last1] < dd->move_position[move]; | 31 | return arg->move_position[arg->last1] < arg->move_position[m]; |
| 27 | 32 | ||
| 28 | return true; | 33 | return true; |
| 29 | } | 34 | } |
| 30 | 35 | ||
| 36 | static bool | ||
| 37 | cancel_niss(DfsArg *arg) | ||
| 38 | { | ||
| 39 | return !possible_next(arg->last2, arg->last1, arg->last1inv) && | ||
| 40 | !(commute(arg->last1inv, arg->last2inv) && | ||
| 41 | arg->last2inv != NULLMOVE && | ||
| 42 | possible_next(arg->last2, arg->last1, arg->last2inv)); | ||
| 43 | } | ||
| 44 | |||
| 31 | static void | 45 | static void |
| 32 | dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | 46 | copy_dfsarg(DfsArg *src, DfsArg *dst) |
| 33 | { | 47 | { |
| 34 | if (dfs_stop(c, s, opts, dd)) | 48 | dst->step = src->step; |
| 49 | dst->opts = src->opts; | ||
| 50 | dst->cube = src->cube; | ||
| 51 | dst->inverse = src->inverse; | ||
| 52 | dst->d = src->d; | ||
| 53 | dst->badmoves = src->badmoves; | ||
| 54 | dst->badmovesinv = src->badmovesinv; | ||
| 55 | dst->niss = src->niss; | ||
| 56 | dst->last1 = src->last1; | ||
| 57 | dst->last2 = src->last2; | ||
| 58 | dst->last1inv = src->last1inv; | ||
| 59 | dst->last2inv = src->last2inv; | ||
| 60 | dst->sols = src->sols; | ||
| 61 | dst->sols_mutex = src->sols_mutex; | ||
| 62 | dst->current_alg = src->current_alg; | ||
| 63 | dst->sorted_moves = src->sorted_moves; | ||
| 64 | dst->move_position = src->move_position; | ||
| 65 | |||
| 66 | copy_estimatedata(src->ed, dst->ed); | ||
| 67 | } | ||
| 68 | |||
| 69 | static void | ||
| 70 | dfs(DfsArg *arg) | ||
| 71 | { | ||
| 72 | bool sw = false; | ||
| 73 | |||
| 74 | if (dfs_stop(arg)) | ||
| 35 | return; | 75 | return; |
| 36 | 76 | ||
| 37 | if (dfs_check_solved(s, opts, dd)) | 77 | if (dfs_check_solved(arg)) |
| 38 | return; | 78 | return; |
| 39 | 79 | ||
| 40 | dfs_branch(c, s, opts, dd); | 80 | if (arg->step->final && (sw = dfs_switch_final(arg))) |
| 81 | invert_branch(arg); | ||
| 82 | dfs_branch(arg); | ||
| 83 | |||
| 84 | if (arg->opts->can_niss && !arg->niss && niss_makes_sense(arg)) | ||
| 85 | dfs_niss(arg); | ||
| 41 | 86 | ||
| 42 | if (opts->can_niss && !dd->niss) | 87 | if (sw) |
| 43 | dfs_niss(c, s, opts, dd); | 88 | invert_branch(arg); |
| 44 | } | 89 | } |
| 45 | 90 | ||
| 46 | static void | 91 | static void |
| 47 | dfs_branch(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | 92 | dfs_branch(DfsArg *arg) |
| 48 | { | 93 | { |
| 49 | bool b = false; | ||
| 50 | int i; | 94 | int i; |
| 51 | uint64_t mm; | 95 | Move m; |
| 52 | Move m, l1, l2; | 96 | DfsArg *newarg; |
| 53 | LocalInfo li; | ||
| 54 | 97 | ||
| 55 | l1 = dd->last1; | 98 | newarg = malloc(sizeof(DfsArg)); |
| 56 | l2 = dd->last2; | 99 | newarg->ed = malloc(sizeof(EstimateData)); |
| 57 | li = *(dd->ed->li); | ||
| 58 | mm = dd->ed->movebitmask; | ||
| 59 | 100 | ||
| 60 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { | 101 | for (i = 0; arg->sorted_moves[i] != NULLMOVE; i++) { |
| 61 | if (b) | 102 | m = arg->sorted_moves[i]; |
| 62 | break; | 103 | if (allowed_next(m, arg)) { |
| 63 | 104 | copy_dfsarg(arg, newarg); | |
| 64 | m = dd->sorted_moves[i]; | 105 | newarg->last2 = arg->last1; |
| 65 | if (allowed_next(m, dd, mm)) { | 106 | newarg->last1 = m; |
| 66 | dd->last2 = dd->last1; | 107 | newarg->cube = apply_move(m, arg->cube); |
| 67 | dd->last1 = m; | 108 | append_move(arg->current_alg, m, newarg->niss); |
| 68 | append_move(dd->current_alg, m, dd->niss); | ||
| 69 | 109 | ||
| 70 | dfs(apply_move(m, c), s, opts, dd); | 110 | dfs(newarg); |
| 71 | 111 | ||
| 72 | dd->current_alg->len--; | 112 | arg->current_alg->len--; |
| 73 | dd->last2 = l2; | ||
| 74 | dd->last1 = l1; | ||
| 75 | *(dd->ed->li) = li; | ||
| 76 | } | 113 | } |
| 77 | } | 114 | } |
| 115 | |||
| 116 | free(newarg->ed); | ||
| 117 | free(newarg); | ||
| 78 | } | 118 | } |
| 79 | 119 | ||
| 80 | static bool | 120 | static bool |
| 81 | dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd) | 121 | dfs_check_solved(DfsArg *arg) |
| 82 | { | 122 | { |
| 83 | if (dd->lb != 0) | 123 | if (!arg->step->is_done(arg->cube)) |
| 84 | return false; | 124 | return false; |
| 85 | 125 | ||
| 86 | if (dd->current_alg->len == dd->d) { | 126 | if (arg->current_alg->len == arg->d) { |
| 87 | if (s->is_valid(dd->current_alg) || opts->all) { | 127 | if ((arg->step->is_valid(arg->current_alg) || arg->opts->all) |
| 88 | pthread_mutex_lock(dd->sols_mutex); | 128 | && (!arg->step->final || !cancel_niss(arg))) { |
| 89 | if (dd->sols->len < opts->max_solutions) | 129 | pthread_mutex_lock(arg->sols_mutex); |
| 90 | append_alg(dd->sols, dd->current_alg); | 130 | if (arg->sols->len < arg->opts->max_solutions) |
| 91 | pthread_mutex_unlock(dd->sols_mutex); | 131 | append_alg(arg->sols, arg->current_alg); |
| 132 | pthread_mutex_unlock(arg->sols_mutex); | ||
| 92 | } | 133 | } |
| 93 | 134 | ||
| 94 | if (opts->verbose) | 135 | if (arg->opts->verbose) |
| 95 | print_alg(dd->current_alg, false); | 136 | print_alg(arg->current_alg, false); |
| 96 | } | 137 | } |
| 97 | 138 | ||
| 98 | return true; | 139 | return true; |
| 99 | } | 140 | } |
| 100 | 141 | ||
| 101 | static void | 142 | static void |
| 102 | dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | 143 | dfs_niss(DfsArg *arg) |
| 103 | { | 144 | { |
| 104 | Move l1, l2; | 145 | DfsArg *newarg; |
| 105 | EstimateData *ed; | ||
| 106 | |||
| 107 | l1 = dd->last1; | ||
| 108 | l2 = dd->last2; | ||
| 109 | 146 | ||
| 110 | ed = malloc(sizeof(EstimateData)); | 147 | newarg = malloc(sizeof(DfsArg)); |
| 111 | ed->cube = apply_move(inverse_move(l1), (Cube){0}); | 148 | newarg->ed = malloc(sizeof(EstimateData)); |
| 112 | ed->target = 1; | ||
| 113 | 149 | ||
| 114 | if (dd->current_alg->len == 0 || s->estimate(ed)) { | 150 | copy_dfsarg(arg, newarg); |
| 115 | dd->niss = true; | 151 | swapmove(&(newarg->last1), &(newarg->last1inv)); |
| 116 | dd->last1 = NULLMOVE; | 152 | swapmove(&(newarg->last2), &(newarg->last2inv)); |
| 117 | dd->last2 = NULLMOVE; | 153 | newarg->niss = !(arg->niss); |
| 154 | newarg->cube = inverse_cube(arg->cube); | ||
| 118 | 155 | ||
| 119 | dfs(inverse_cube(c), s, opts, dd); | 156 | dfs(newarg); |
| 120 | 157 | ||
| 121 | dd->last1 = l1; | 158 | free(newarg->ed); |
| 122 | dd->last2 = l2; | 159 | free(newarg); |
| 123 | dd->niss = false; | ||
| 124 | } | ||
| 125 | |||
| 126 | free(ed); | ||
| 127 | } | 160 | } |
| 128 | 161 | ||
| 129 | static bool | 162 | static bool |
| 130 | dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | 163 | dfs_stop(DfsArg *arg) |
| 131 | { | 164 | { |
| 165 | int lowerbound; | ||
| 132 | bool b; | 166 | bool b; |
| 133 | 167 | ||
| 134 | dd->ed->cube = c; | 168 | lowerbound = arg->step->estimate(arg); |
| 135 | dd->ed->target = dd->d - dd->current_alg->len; | 169 | if (arg->opts->can_niss && !arg->niss) |
| 136 | dd->ed->lastmove = dd->last1; | 170 | lowerbound = MIN(1, lowerbound); |
| 137 | dd->ed->movebitmask = 0; | ||
| 138 | |||
| 139 | dd->lb = s->estimate(dd->ed); | ||
| 140 | if (opts->can_niss && !dd->niss) | ||
| 141 | dd->lb = MIN(1, dd->lb); | ||
| 142 | 171 | ||
| 143 | if (dd->current_alg->len + dd->lb > dd->d) { | 172 | if (arg->current_alg->len + lowerbound > arg->d) { |
| 144 | b = true; | 173 | b = true; |
| 145 | } else { | 174 | } else { |
| 146 | pthread_mutex_lock(dd->sols_mutex); | 175 | pthread_mutex_lock(arg->sols_mutex); |
| 147 | b = dd->sols->len >= opts->max_solutions; | 176 | b = arg->sols->len >= arg->opts->max_solutions; |
| 148 | pthread_mutex_unlock(dd->sols_mutex); | 177 | pthread_mutex_unlock(arg->sols_mutex); |
| 149 | } | 178 | } |
| 150 | 179 | ||
| 151 | return b; | 180 | return b; |
| 152 | } | 181 | } |
| 153 | 182 | ||
| 183 | static bool | ||
| 184 | dfs_switch_final(DfsArg *arg) | ||
| 185 | { | ||
| 186 | int i, bn, bi; | ||
| 187 | |||
| 188 | for (bn = 0, i = 0; arg->sorted_moves[i] != NULLMOVE; i++) | ||
| 189 | if (allowed_next(arg->sorted_moves[i], arg)) | ||
| 190 | bn++; | ||
| 191 | |||
| 192 | swapmove(&(arg->last1), &(arg->last1inv)); | ||
| 193 | swapmove(&(arg->last2), &(arg->last2inv)); | ||
| 194 | swapu64(&(arg->badmoves), &(arg->badmovesinv)); | ||
| 195 | |||
| 196 | for (bi = 0, i = 0; arg->sorted_moves[i] != NULLMOVE; i++) | ||
| 197 | if (allowed_next(arg->sorted_moves[i], arg)) | ||
| 198 | bi++; | ||
| 199 | |||
| 200 | swapmove(&(arg->last1), &(arg->last1inv)); | ||
| 201 | swapmove(&(arg->last2), &(arg->last2inv)); | ||
| 202 | swapu64(&(arg->badmoves), &(arg->badmovesinv)); | ||
| 203 | |||
| 204 | return bi < bn; | ||
| 205 | } | ||
| 206 | |||
| 154 | static void * | 207 | static void * |
| 155 | instance_thread(void *arg) | 208 | instance_thread(void *arg) |
| 156 | { | 209 | { |
| @@ -158,7 +211,7 @@ instance_thread(void *arg) | |||
| 158 | Cube c; | 211 | Cube c; |
| 159 | ThreadDataSolve *td; | 212 | ThreadDataSolve *td; |
| 160 | AlgListNode *node; | 213 | AlgListNode *node; |
| 161 | DfsData dd; | 214 | DfsArg darg; |
| 162 | 215 | ||
| 163 | td = (ThreadDataSolve *)arg; | 216 | td = (ThreadDataSolve *)arg; |
| 164 | 217 | ||
| @@ -179,34 +232,53 @@ instance_thread(void *arg) | |||
| 179 | apply_move(node->alg->move[0], inverse_cube(td->cube)) : | 232 | apply_move(node->alg->move[0], inverse_cube(td->cube)) : |
| 180 | apply_move(node->alg->move[0], td->cube); | 233 | apply_move(node->alg->move[0], td->cube); |
| 181 | 234 | ||
| 182 | dd.d = td->depth; | 235 | darg.step = td->step; |
| 183 | dd.m = 1; | 236 | darg.opts = td->opts; |
| 184 | dd.niss = node->alg->inv[0]; | 237 | darg.cube = c; |
| 185 | dd.lb = -1; | 238 | darg.d = td->depth; |
| 186 | dd.last1 = node->alg->move[0]; | 239 | darg.niss = node->alg->inv[0]; |
| 187 | dd.last2 = NULLMOVE; | 240 | darg.last1 = node->alg->move[0]; |
| 188 | dd.sols = td->sols; | 241 | darg.last2 = NULLMOVE; |
| 189 | dd.sols_mutex = td->sols_mutex; | 242 | darg.last1inv = NULLMOVE; |
| 190 | dd.current_alg = new_alg(""); | 243 | darg.last2inv = NULLMOVE; |
| 191 | append_move(dd.current_alg, node->alg->move[0], | 244 | darg.sols = td->sols; |
| 245 | darg.sols_mutex = td->sols_mutex; | ||
| 246 | darg.current_alg = new_alg(""); | ||
| 247 | append_move(darg.current_alg, node->alg->move[0], | ||
| 192 | node->alg->inv[0]); | 248 | node->alg->inv[0]); |
| 193 | dd.sorted_moves = td->sorted_moves; | 249 | darg.sorted_moves = td->sorted_moves; |
| 194 | dd.move_position = td->move_position; | 250 | darg.move_position = td->move_position; |
| 195 | dd.ed = malloc(sizeof(EstimateData)); | 251 | darg.ed = new_estimatedata(); |
| 196 | dd.ed->movebitmask = 0; | 252 | darg.badmoves = 0; |
| 197 | dd.ed->li = new_localinfo(); | 253 | darg.badmovesinv = 0; |
| 198 | 254 | ||
| 199 | dfs(c, td->step, td->opts, &dd); | 255 | dfs(&darg); |
| 200 | 256 | ||
| 201 | free_alg(dd.current_alg); | 257 | free_alg(darg.current_alg); |
| 202 | free_localinfo(dd.ed->li); | 258 | free_estimatedata(darg.ed); |
| 203 | free(dd.ed); | ||
| 204 | } | 259 | } |
| 205 | 260 | ||
| 206 | return NULL; | 261 | return NULL; |
| 207 | } | 262 | } |
| 208 | 263 | ||
| 209 | static void | 264 | static void |
| 265 | invert_branch(DfsArg *arg) | ||
| 266 | { | ||
| 267 | Cube aux; | ||
| 268 | |||
| 269 | aux = arg->cube; | ||
| 270 | arg->cube = is_solved(arg->inverse) ? | ||
| 271 | inverse_cube(arg->cube) : arg->inverse; | ||
| 272 | arg->inverse = aux; | ||
| 273 | |||
| 274 | swapu64(&(arg->badmoves), &(arg->badmovesinv)); | ||
| 275 | arg->niss = !(arg->niss); | ||
| 276 | swapmove(&(arg->last1), &(arg->last1inv)); | ||
| 277 | swapmove(&(arg->last2), &(arg->last2inv)); | ||
| 278 | invert_estimatedata(arg->ed); | ||
| 279 | } | ||
| 280 | |||
| 281 | static void | ||
| 210 | multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) | 282 | multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) |
| 211 | { | 283 | { |
| 212 | int i, *move_position; | 284 | int i, *move_position; |
| @@ -233,6 +305,8 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) | |||
| 233 | 305 | ||
| 234 | for (i = 0; sorted_moves[i] != NULLMOVE; i++) { | 306 | for (i = 0; sorted_moves[i] != NULLMOVE; i++) { |
| 235 | alg = new_alg(""); | 307 | alg = new_alg(""); |
| 308 | /* TODO: start on inverse also in case of final step | ||
| 309 | and ed->sw true */ | ||
| 236 | append_move(alg, sorted_moves[i], false); | 310 | append_move(alg, sorted_moves[i], false); |
| 237 | append_alg(start, alg); | 311 | append_alg(start, alg); |
| 238 | if (opts->can_niss) { | 312 | if (opts->can_niss) { |
| @@ -270,6 +344,15 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) | |||
| 270 | free(sorted_moves); | 344 | free(sorted_moves); |
| 271 | } | 345 | } |
| 272 | 346 | ||
| 347 | static bool | ||
| 348 | niss_makes_sense(DfsArg *arg) | ||
| 349 | { | ||
| 350 | Cube testcube; | ||
| 351 | |||
| 352 | testcube = apply_move(inverse_move(arg->last1), (Cube){0}); | ||
| 353 | return arg->current_alg->len == 0 || arg->step->is_done(testcube); | ||
| 354 | } | ||
| 355 | |||
| 273 | /* Public functions **********************************************************/ | 356 | /* Public functions **********************************************************/ |
| 274 | 357 | ||
| 275 | AlgList * | 358 | AlgList * |
| @@ -279,10 +362,8 @@ solve(Cube cube, Step *step, SolveOptions *opts) | |||
| 279 | AlgList *sols; | 362 | AlgList *sols; |
| 280 | AlgListNode *node; | 363 | AlgListNode *node; |
| 281 | Cube c; | 364 | Cube c; |
| 282 | EstimateData *ed; | ||
| 283 | bool b; | ||
| 284 | 365 | ||
| 285 | prepare_step(step, opts->nthreads); | 366 | prepare_step(step, opts); |
| 286 | 367 | ||
| 287 | if (step->detect != NULL) | 368 | if (step->detect != NULL) |
| 288 | step->pre_trans = step->detect(cube); | 369 | step->pre_trans = step->detect(cube); |
| @@ -296,19 +377,9 @@ solve(Cube cube, Step *step, SolveOptions *opts) | |||
| 296 | return sols; | 377 | return sols; |
| 297 | } | 378 | } |
| 298 | 379 | ||
| 299 | if (opts->min_moves == 0) { | 380 | if (opts->min_moves == 0 && step->is_done(cube)) { |
| 300 | ed = malloc(sizeof(EstimateData)); | 381 | append_alg(sols, new_alg("")); |
| 301 | ed->cube = cube; | 382 | return sols; |
| 302 | ed->target = 0; | ||
| 303 | ed->li = new_localinfo(); | ||
| 304 | b = step->estimate(ed) == 0; | ||
| 305 | free_localinfo(ed->li); | ||
| 306 | free(ed); | ||
| 307 | |||
| 308 | if (b) { | ||
| 309 | append_alg(sols, new_alg("")); | ||
| 310 | return sols; | ||
| 311 | } | ||
| 312 | } | 383 | } |
| 313 | 384 | ||
| 314 | for (d = opts->min_moves; | 385 | for (d = opts->min_moves; |
| @@ -323,8 +394,11 @@ solve(Cube cube, Step *step, SolveOptions *opts) | |||
| 323 | multidfs(c, step, opts, sols, d); | 394 | multidfs(c, step, opts, sols, d); |
| 324 | } | 395 | } |
| 325 | 396 | ||
| 326 | for (node = sols->first; node != NULL; node = node->next) | 397 | for (node = sols->first; node != NULL; node = node->next) { |
| 327 | transform_alg(inverse_trans(step->pre_trans), node->alg); | 398 | transform_alg(inverse_trans(step->pre_trans), node->alg); |
| 399 | if (step->final) | ||
| 400 | unniss(node->alg); | ||
| 401 | } | ||
| 328 | 402 | ||
| 329 | return sols; | 403 | return sols; |
| 330 | } | 404 | } |
diff --git a/src/steps.c b/src/steps.c index abb2918..ccf33df 100644 --- a/src/steps.c +++ b/src/steps.c | |||
| @@ -5,28 +5,37 @@ | |||
| 5 | /* Checkers, estimators and validators ***************************************/ | 5 | /* Checkers, estimators and validators ***************************************/ |
| 6 | 6 | ||
| 7 | static bool check_centers(Cube cube); | 7 | static bool check_centers(Cube cube); |
| 8 | static bool check_coany_HTM(Cube cube); | ||
| 9 | static bool check_coud_HTM(Cube cube); | ||
| 10 | static bool check_coany_URF(Cube cube); | ||
| 11 | static bool check_coud_URF(Cube cube); | ||
| 12 | static bool check_corners_HTM(Cube cube); | ||
| 13 | static bool check_corners_URF(Cube cube); | ||
| 14 | static bool check_cornershtr(Cube cube); | ||
| 15 | static bool check_eoany(Cube cube); | ||
| 8 | static bool check_eofb(Cube cube); | 16 | static bool check_eofb(Cube cube); |
| 17 | static bool check_drany(Cube cube); | ||
| 9 | static bool check_drud(Cube cube); | 18 | static bool check_drud(Cube cube); |
| 10 | static bool check_htr(Cube cube); | 19 | static bool check_htr(Cube cube); |
| 11 | 20 | ||
| 12 | static int estimate_eoany_HTM(EstimateData *ed); | 21 | static int estimate_eoany_HTM(DfsArg *arg); |
| 13 | static int estimate_eofb_HTM(EstimateData *ed); | 22 | static int estimate_eofb_HTM(DfsArg *arg); |
| 14 | static int estimate_coany_HTM(EstimateData *ed); | 23 | static int estimate_coany_HTM(DfsArg *arg); |
| 15 | static int estimate_coud_HTM(EstimateData *ed); | 24 | static int estimate_coud_HTM(DfsArg *arg); |
| 16 | static int estimate_coany_URF(EstimateData *ed); | 25 | static int estimate_coany_URF(DfsArg *arg); |
| 17 | static int estimate_coud_URF(EstimateData *ed); | 26 | static int estimate_coud_URF(DfsArg *arg); |
| 18 | static int estimate_corners_HTM(EstimateData *ed); | 27 | static int estimate_corners_HTM(DfsArg *arg); |
| 19 | static int estimate_cornershtr_HTM(EstimateData *ed); | 28 | static int estimate_cornershtr_HTM(DfsArg *arg); |
| 20 | static int estimate_corners_URF(EstimateData *ed); | 29 | static int estimate_corners_URF(DfsArg *arg); |
| 21 | static int estimate_cornershtr_URF(EstimateData *ed); | 30 | static int estimate_cornershtr_URF(DfsArg *arg); |
| 22 | static int estimate_drany_HTM(EstimateData *ed); | 31 | static int estimate_drany_HTM(DfsArg *arg); |
| 23 | static int estimate_drud_HTM(EstimateData *ed); | 32 | static int estimate_drud_HTM(DfsArg *arg); |
| 24 | static int estimate_drud_eofb(EstimateData *ed); | 33 | static int estimate_drud_eofb(DfsArg *arg); |
| 25 | static int estimate_dr_eofb(EstimateData *ed); | 34 | static int estimate_dr_eofb(DfsArg *arg); |
| 26 | static int estimate_drudfin_drud(EstimateData *ed); | 35 | static int estimate_drudfin_drud(DfsArg *arg); |
| 27 | static int estimate_htr_drud(EstimateData *ed); | 36 | static int estimate_htr_drud(DfsArg *arg); |
| 28 | static int estimate_htrfin_htr(EstimateData *ed); | 37 | static int estimate_htrfin_htr(DfsArg *arg); |
| 29 | static int estimate_optimal_HTM(EstimateData *ed); | 38 | static int estimate_optimal_HTM(DfsArg *arg); |
| 30 | 39 | ||
| 31 | static bool always_valid(Alg *alg); | 40 | static bool always_valid(Alg *alg); |
| 32 | static bool validate_singlecw_ending(Alg *alg); | 41 | static bool validate_singlecw_ending(Alg *alg); |
| @@ -51,6 +60,8 @@ optimal_HTM = { | |||
| 51 | .shortname = "optimal", | 60 | .shortname = "optimal", |
| 52 | .name = "Optimal solve (in HTM)", | 61 | .name = "Optimal solve (in HTM)", |
| 53 | 62 | ||
| 63 | .final = true, | ||
| 64 | .is_done = is_solved, | ||
| 54 | .estimate = estimate_optimal_HTM, | 65 | .estimate = estimate_optimal_HTM, |
| 55 | .ready = check_centers, | 66 | .ready = check_centers, |
| 56 | .ready_msg = check_centers_msg, | 67 | .ready_msg = check_centers_msg, |
| @@ -69,6 +80,8 @@ eoany_HTM = { | |||
| 69 | .shortname = "eo", | 80 | .shortname = "eo", |
| 70 | .name = "EO on any axis", | 81 | .name = "EO on any axis", |
| 71 | 82 | ||
| 83 | .final = false, | ||
| 84 | .is_done = check_eoany, | ||
| 72 | .estimate = estimate_eoany_HTM, | 85 | .estimate = estimate_eoany_HTM, |
| 73 | .ready = check_centers, | 86 | .ready = check_centers, |
| 74 | .ready_msg = check_centers_msg, | 87 | .ready_msg = check_centers_msg, |
| @@ -86,6 +99,8 @@ eofb_HTM = { | |||
| 86 | .shortname = "eofb", | 99 | .shortname = "eofb", |
| 87 | .name = "EO on F/B", | 100 | .name = "EO on F/B", |
| 88 | 101 | ||
| 102 | .final = false, | ||
| 103 | .is_done = check_eofb, | ||
| 89 | .estimate = estimate_eofb_HTM, | 104 | .estimate = estimate_eofb_HTM, |
| 90 | .ready = check_centers, | 105 | .ready = check_centers, |
| 91 | .ready_msg = check_centers_msg, | 106 | .ready_msg = check_centers_msg, |
| @@ -103,6 +118,8 @@ eorl_HTM = { | |||
| 103 | .shortname = "eorl", | 118 | .shortname = "eorl", |
| 104 | .name = "EO on R/L", | 119 | .name = "EO on R/L", |
| 105 | 120 | ||
| 121 | .final = false, | ||
| 122 | .is_done = check_eofb, | ||
| 106 | .estimate = estimate_eofb_HTM, | 123 | .estimate = estimate_eofb_HTM, |
| 107 | .ready = check_centers, | 124 | .ready = check_centers, |
| 108 | .ready_msg = check_centers_msg, | 125 | .ready_msg = check_centers_msg, |
| @@ -120,6 +137,8 @@ eoud_HTM = { | |||
| 120 | .shortname = "eoud", | 137 | .shortname = "eoud", |
| 121 | .name = "EO on U/D", | 138 | .name = "EO on U/D", |
| 122 | 139 | ||
| 140 | .final = false, | ||
| 141 | .is_done = check_eofb, | ||
| 123 | .estimate = estimate_eofb_HTM, | 142 | .estimate = estimate_eofb_HTM, |
| 124 | .ready = check_centers, | 143 | .ready = check_centers, |
| 125 | .ready_msg = check_centers_msg, | 144 | .ready_msg = check_centers_msg, |
| @@ -138,6 +157,8 @@ coany_HTM = { | |||
| 138 | .shortname = "co", | 157 | .shortname = "co", |
| 139 | .name = "CO on any axis", | 158 | .name = "CO on any axis", |
| 140 | 159 | ||
| 160 | .final = false, | ||
| 161 | .is_done = check_coany_HTM, | ||
| 141 | .estimate = estimate_coany_HTM, | 162 | .estimate = estimate_coany_HTM, |
| 142 | .ready = NULL, | 163 | .ready = NULL, |
| 143 | .is_valid = validate_singlecw_ending, | 164 | .is_valid = validate_singlecw_ending, |
| @@ -154,6 +175,8 @@ coud_HTM = { | |||
| 154 | .shortname = "coud", | 175 | .shortname = "coud", |
| 155 | .name = "CO on U/D", | 176 | .name = "CO on U/D", |
| 156 | 177 | ||
| 178 | .final = false, | ||
| 179 | .is_done = check_coud_HTM, | ||
| 157 | .estimate = estimate_coud_HTM, | 180 | .estimate = estimate_coud_HTM, |
| 158 | .ready = NULL, | 181 | .ready = NULL, |
| 159 | .is_valid = validate_singlecw_ending, | 182 | .is_valid = validate_singlecw_ending, |
| @@ -170,6 +193,8 @@ corl_HTM = { | |||
| 170 | .shortname = "corl", | 193 | .shortname = "corl", |
| 171 | .name = "CO on R/L", | 194 | .name = "CO on R/L", |
| 172 | 195 | ||
| 196 | .final = false, | ||
| 197 | .is_done = check_coud_HTM, | ||
| 173 | .estimate = estimate_coud_HTM, | 198 | .estimate = estimate_coud_HTM, |
| 174 | .ready = NULL, | 199 | .ready = NULL, |
| 175 | .is_valid = validate_singlecw_ending, | 200 | .is_valid = validate_singlecw_ending, |
| @@ -186,6 +211,8 @@ cofb_HTM = { | |||
| 186 | .shortname = "cofb", | 211 | .shortname = "cofb", |
| 187 | .name = "CO on F/B", | 212 | .name = "CO on F/B", |
| 188 | 213 | ||
| 214 | .final = false, | ||
| 215 | .is_done = check_coud_HTM, | ||
| 189 | .estimate = estimate_coud_HTM, | 216 | .estimate = estimate_coud_HTM, |
| 190 | .ready = NULL, | 217 | .ready = NULL, |
| 191 | .is_valid = validate_singlecw_ending, | 218 | .is_valid = validate_singlecw_ending, |
| @@ -202,6 +229,8 @@ coany_URF = { | |||
| 202 | .shortname = "co-URF", | 229 | .shortname = "co-URF", |
| 203 | .name = "CO any axis (URF moveset)", | 230 | .name = "CO any axis (URF moveset)", |
| 204 | 231 | ||
| 232 | .final = false, | ||
| 233 | .is_done = check_coany_URF, | ||
| 205 | .estimate = estimate_coany_URF, | 234 | .estimate = estimate_coany_URF, |
| 206 | .ready = NULL, | 235 | .ready = NULL, |
| 207 | .is_valid = validate_singlecw_ending, | 236 | .is_valid = validate_singlecw_ending, |
| @@ -218,6 +247,8 @@ coud_URF = { | |||
| 218 | .shortname = "coud-URF", | 247 | .shortname = "coud-URF", |
| 219 | .name = "CO on U/D (URF moveset)", | 248 | .name = "CO on U/D (URF moveset)", |
| 220 | 249 | ||
| 250 | .final = false, | ||
| 251 | .is_done = check_coud_URF, | ||
| 221 | .estimate = estimate_coud_URF, | 252 | .estimate = estimate_coud_URF, |
| 222 | .ready = NULL, | 253 | .ready = NULL, |
| 223 | .is_valid = validate_singlecw_ending, | 254 | .is_valid = validate_singlecw_ending, |
| @@ -234,6 +265,8 @@ corl_URF = { | |||
| 234 | .shortname = "corl-URF", | 265 | .shortname = "corl-URF", |
| 235 | .name = "CO on R/L (URF moveset)", | 266 | .name = "CO on R/L (URF moveset)", |
| 236 | 267 | ||
| 268 | .final = false, | ||
| 269 | .is_done = check_coud_URF, | ||
| 237 | .estimate = estimate_coud_URF, | 270 | .estimate = estimate_coud_URF, |
| 238 | .ready = NULL, | 271 | .ready = NULL, |
| 239 | .is_valid = validate_singlecw_ending, | 272 | .is_valid = validate_singlecw_ending, |
| @@ -250,6 +283,8 @@ cofb_URF = { | |||
| 250 | .shortname = "cofb-URF", | 283 | .shortname = "cofb-URF", |
| 251 | .name = "CO on F/B (URF moveset)", | 284 | .name = "CO on F/B (URF moveset)", |
| 252 | 285 | ||
| 286 | .final = false, | ||
| 287 | .is_done = check_coud_URF, | ||
| 253 | .estimate = estimate_coud_URF, | 288 | .estimate = estimate_coud_URF, |
| 254 | .ready = NULL, | 289 | .ready = NULL, |
| 255 | .is_valid = validate_singlecw_ending, | 290 | .is_valid = validate_singlecw_ending, |
| @@ -267,6 +302,8 @@ cornershtr_HTM = { | |||
| 267 | .shortname = "chtr", | 302 | .shortname = "chtr", |
| 268 | .name = "Solve corners to HTR state", | 303 | .name = "Solve corners to HTR state", |
| 269 | 304 | ||
| 305 | .final = false, | ||
| 306 | .is_done = check_cornershtr, | ||
| 270 | .estimate = estimate_cornershtr_HTM, | 307 | .estimate = estimate_cornershtr_HTM, |
| 271 | .ready = NULL, | 308 | .ready = NULL, |
| 272 | .is_valid = validate_singlecw_ending, | 309 | .is_valid = validate_singlecw_ending, |
| @@ -283,6 +320,8 @@ cornershtr_URF = { | |||
| 283 | .shortname = "chtr-URF", | 320 | .shortname = "chtr-URF", |
| 284 | .name = "Solve corners to HTR state (URF moveset)", | 321 | .name = "Solve corners to HTR state (URF moveset)", |
| 285 | 322 | ||
| 323 | .final = false, | ||
| 324 | .is_done = check_cornershtr, | ||
| 286 | .estimate = estimate_cornershtr_URF, | 325 | .estimate = estimate_cornershtr_URF, |
| 287 | .ready = NULL, | 326 | .ready = NULL, |
| 288 | .is_valid = validate_singlecw_ending, | 327 | .is_valid = validate_singlecw_ending, |
| @@ -299,6 +338,8 @@ corners_HTM = { | |||
| 299 | .shortname = "corners", | 338 | .shortname = "corners", |
| 300 | .name = "Solve corners", | 339 | .name = "Solve corners", |
| 301 | 340 | ||
| 341 | .final = true, | ||
| 342 | .is_done = check_corners_HTM, | ||
| 302 | .estimate = estimate_corners_HTM, | 343 | .estimate = estimate_corners_HTM, |
| 303 | .ready = NULL, | 344 | .ready = NULL, |
| 304 | .is_valid = always_valid, | 345 | .is_valid = always_valid, |
| @@ -315,6 +356,8 @@ corners_URF = { | |||
| 315 | .shortname = "corners-URF", | 356 | .shortname = "corners-URF", |
| 316 | .name = "Solve corners (URF moveset)", | 357 | .name = "Solve corners (URF moveset)", |
| 317 | 358 | ||
| 359 | .final = true, /* TODO: check if this works with reorient */ | ||
| 360 | .is_done = check_corners_URF, | ||
| 318 | .estimate = estimate_corners_URF, | 361 | .estimate = estimate_corners_URF, |
| 319 | .ready = NULL, | 362 | .ready = NULL, |
| 320 | .is_valid = always_valid, | 363 | .is_valid = always_valid, |
| @@ -332,6 +375,8 @@ drany_HTM = { | |||
| 332 | .shortname = "dr", | 375 | .shortname = "dr", |
| 333 | .name = "DR on any axis", | 376 | .name = "DR on any axis", |
| 334 | 377 | ||
| 378 | .final = false, | ||
| 379 | .is_done = check_drany, | ||
| 335 | .estimate = estimate_drany_HTM, | 380 | .estimate = estimate_drany_HTM, |
| 336 | .ready = check_centers, | 381 | .ready = check_centers, |
| 337 | .ready_msg = check_centers_msg, | 382 | .ready_msg = check_centers_msg, |
| @@ -349,6 +394,8 @@ drud_HTM = { | |||
| 349 | .shortname = "drud", | 394 | .shortname = "drud", |
| 350 | .name = "DR on U/D", | 395 | .name = "DR on U/D", |
| 351 | 396 | ||
| 397 | .final = false, | ||
| 398 | .is_done = check_drud, | ||
| 352 | .estimate = estimate_drud_HTM, | 399 | .estimate = estimate_drud_HTM, |
| 353 | .ready = check_centers, | 400 | .ready = check_centers, |
| 354 | .ready_msg = check_centers_msg, | 401 | .ready_msg = check_centers_msg, |
| @@ -366,6 +413,8 @@ drrl_HTM = { | |||
| 366 | .shortname = "drrl", | 413 | .shortname = "drrl", |
| 367 | .name = "DR on R/L", | 414 | .name = "DR on R/L", |
| 368 | 415 | ||
| 416 | .final = false, | ||
| 417 | .is_done = check_drud, | ||
| 369 | .estimate = estimate_drud_HTM, | 418 | .estimate = estimate_drud_HTM, |
| 370 | .ready = check_centers, | 419 | .ready = check_centers, |
| 371 | .ready_msg = check_centers_msg, | 420 | .ready_msg = check_centers_msg, |
| @@ -383,6 +432,8 @@ drfb_HTM = { | |||
| 383 | .shortname = "drfb", | 432 | .shortname = "drfb", |
| 384 | .name = "DR on F/B", | 433 | .name = "DR on F/B", |
| 385 | 434 | ||
| 435 | .final = false, | ||
| 436 | .is_done = check_drud, | ||
| 386 | .estimate = estimate_drud_HTM, | 437 | .estimate = estimate_drud_HTM, |
| 387 | .ready = check_centers, | 438 | .ready = check_centers, |
| 388 | .ready_msg = check_centers_msg, | 439 | .ready_msg = check_centers_msg, |
| @@ -401,6 +452,8 @@ dr_eo = { | |||
| 401 | .shortname = "dr-eo", | 452 | .shortname = "dr-eo", |
| 402 | .name = "DR without breaking EO (automatically detected)", | 453 | .name = "DR without breaking EO (automatically detected)", |
| 403 | 454 | ||
| 455 | .final = false, | ||
| 456 | .is_done = check_drud, | ||
| 404 | .estimate = estimate_dr_eofb, | 457 | .estimate = estimate_dr_eofb, |
| 405 | .ready = check_eofb, | 458 | .ready = check_eofb, |
| 406 | .ready_msg = check_eo_msg, | 459 | .ready_msg = check_eo_msg, |
| @@ -418,6 +471,8 @@ dr_eofb = { | |||
| 418 | .shortname = "dr-eofb", | 471 | .shortname = "dr-eofb", |
| 419 | .name = "DR on U/D or R/L without breaking EO on F/B", | 472 | .name = "DR on U/D or R/L without breaking EO on F/B", |
| 420 | 473 | ||
| 474 | .final = false, | ||
| 475 | .is_done = check_drud, | ||
| 421 | .estimate = estimate_dr_eofb, | 476 | .estimate = estimate_dr_eofb, |
| 422 | .ready = check_eofb, | 477 | .ready = check_eofb, |
| 423 | .ready_msg = check_eo_msg, | 478 | .ready_msg = check_eo_msg, |
| @@ -435,6 +490,8 @@ dr_eorl = { | |||
| 435 | .shortname = "dr-eorl", | 490 | .shortname = "dr-eorl", |
| 436 | .name = "DR on U/D or F/B without breaking EO on R/L", | 491 | .name = "DR on U/D or F/B without breaking EO on R/L", |
| 437 | 492 | ||
| 493 | .final = false, | ||
| 494 | .is_done = check_drud, | ||
| 438 | .estimate = estimate_dr_eofb, | 495 | .estimate = estimate_dr_eofb, |
| 439 | .ready = check_eofb, | 496 | .ready = check_eofb, |
| 440 | .ready_msg = check_eo_msg, | 497 | .ready_msg = check_eo_msg, |
| @@ -452,6 +509,8 @@ dr_eoud = { | |||
| 452 | .shortname = "dr-eoud", | 509 | .shortname = "dr-eoud", |
| 453 | .name = "DR on R/L or F/B without breaking EO on U/D", | 510 | .name = "DR on R/L or F/B without breaking EO on U/D", |
| 454 | 511 | ||
| 512 | .final = false, | ||
| 513 | .is_done = check_drud, | ||
| 455 | .estimate = estimate_dr_eofb, | 514 | .estimate = estimate_dr_eofb, |
| 456 | .ready = check_eofb, | 515 | .ready = check_eofb, |
| 457 | .ready_msg = check_eo_msg, | 516 | .ready_msg = check_eo_msg, |
| @@ -469,6 +528,8 @@ drud_eofb = { | |||
| 469 | .shortname = "drud-eofb", | 528 | .shortname = "drud-eofb", |
| 470 | .name = "DR on U/D without breaking EO on F/B", | 529 | .name = "DR on U/D without breaking EO on F/B", |
| 471 | 530 | ||
| 531 | .final = false, | ||
| 532 | .is_done = check_drud, | ||
| 472 | .estimate = estimate_drud_eofb, | 533 | .estimate = estimate_drud_eofb, |
| 473 | .ready = check_eofb, | 534 | .ready = check_eofb, |
| 474 | .ready_msg = check_eo_msg, | 535 | .ready_msg = check_eo_msg, |
| @@ -486,6 +547,8 @@ drrl_eofb = { | |||
| 486 | .shortname = "drrl-eofb", | 547 | .shortname = "drrl-eofb", |
| 487 | .name = "DR on R/L without breaking EO on F/B", | 548 | .name = "DR on R/L without breaking EO on F/B", |
| 488 | 549 | ||
| 550 | .final = false, | ||
| 551 | .is_done = check_drud, | ||
| 489 | .estimate = estimate_drud_eofb, | 552 | .estimate = estimate_drud_eofb, |
| 490 | .ready = check_eofb, | 553 | .ready = check_eofb, |
| 491 | .ready_msg = check_eo_msg, | 554 | .ready_msg = check_eo_msg, |
| @@ -503,6 +566,8 @@ drud_eorl = { | |||
| 503 | .shortname = "drud-eorl", | 566 | .shortname = "drud-eorl", |
| 504 | .name = "DR on U/D without breaking EO on R/L", | 567 | .name = "DR on U/D without breaking EO on R/L", |
| 505 | 568 | ||
| 569 | .final = false, | ||
| 570 | .is_done = check_drud, | ||
| 506 | .estimate = estimate_drud_eofb, | 571 | .estimate = estimate_drud_eofb, |
| 507 | .ready = check_eofb, | 572 | .ready = check_eofb, |
| 508 | .ready_msg = check_eo_msg, | 573 | .ready_msg = check_eo_msg, |
| @@ -520,6 +585,8 @@ drfb_eorl = { | |||
| 520 | .shortname = "drfb-eorl", | 585 | .shortname = "drfb-eorl", |
| 521 | .name = "DR on F/B without breaking EO on R/L", | 586 | .name = "DR on F/B without breaking EO on R/L", |
| 522 | 587 | ||
| 588 | .final = false, | ||
| 589 | .is_done = check_drud, | ||
| 523 | .estimate = estimate_drud_eofb, | 590 | .estimate = estimate_drud_eofb, |
| 524 | .ready = check_eofb, | 591 | .ready = check_eofb, |
| 525 | .ready_msg = check_eo_msg, | 592 | .ready_msg = check_eo_msg, |
| @@ -537,6 +604,8 @@ drfb_eoud = { | |||
| 537 | .shortname = "drfb-eoud", | 604 | .shortname = "drfb-eoud", |
| 538 | .name = "DR on F/B without breaking EO on U/D", | 605 | .name = "DR on F/B without breaking EO on U/D", |
| 539 | 606 | ||
| 607 | .final = false, | ||
| 608 | .is_done = check_drud, | ||
| 540 | .estimate = estimate_drud_eofb, | 609 | .estimate = estimate_drud_eofb, |
| 541 | .ready = check_eofb, | 610 | .ready = check_eofb, |
| 542 | .ready_msg = check_eo_msg, | 611 | .ready_msg = check_eo_msg, |
| @@ -554,6 +623,8 @@ drrl_eoud = { | |||
| 554 | .shortname = "drrl-eoud", | 623 | .shortname = "drrl-eoud", |
| 555 | .name = "DR on R/L without breaking EO on U/D", | 624 | .name = "DR on R/L without breaking EO on U/D", |
| 556 | 625 | ||
| 626 | .final = false, | ||
| 627 | .is_done = check_drud, | ||
| 557 | .estimate = estimate_drud_eofb, | 628 | .estimate = estimate_drud_eofb, |
| 558 | .ready = check_eofb, | 629 | .ready = check_eofb, |
| 559 | .ready_msg = check_eo_msg, | 630 | .ready_msg = check_eo_msg, |
| @@ -572,6 +643,8 @@ dranyfin_DR = { | |||
| 572 | .shortname = "drfin", | 643 | .shortname = "drfin", |
| 573 | .name = "DR finish on any axis without breaking DR", | 644 | .name = "DR finish on any axis without breaking DR", |
| 574 | 645 | ||
| 646 | .final = true, | ||
| 647 | .is_done = is_solved, | ||
| 575 | .estimate = estimate_drudfin_drud, | 648 | .estimate = estimate_drudfin_drud, |
| 576 | .ready = check_drud, | 649 | .ready = check_drud, |
| 577 | .ready_msg = check_drany_msg, | 650 | .ready_msg = check_drany_msg, |
| @@ -589,6 +662,8 @@ drudfin_drud = { | |||
| 589 | .shortname = "drudfin", | 662 | .shortname = "drudfin", |
| 590 | .name = "DR finish on U/D without breaking DR", | 663 | .name = "DR finish on U/D without breaking DR", |
| 591 | 664 | ||
| 665 | .final = true, | ||
| 666 | .is_done = is_solved, | ||
| 592 | .estimate = estimate_drudfin_drud, | 667 | .estimate = estimate_drudfin_drud, |
| 593 | .ready = check_drud, | 668 | .ready = check_drud, |
| 594 | .ready_msg = check_dr_msg, | 669 | .ready_msg = check_dr_msg, |
| @@ -606,6 +681,8 @@ drrlfin_drrl = { | |||
| 606 | .shortname = "drrlfin", | 681 | .shortname = "drrlfin", |
| 607 | .name = "DR finish on R/L without breaking DR", | 682 | .name = "DR finish on R/L without breaking DR", |
| 608 | 683 | ||
| 684 | .final = true, | ||
| 685 | .is_done = is_solved, | ||
| 609 | .estimate = estimate_drudfin_drud, | 686 | .estimate = estimate_drudfin_drud, |
| 610 | .ready = check_drud, | 687 | .ready = check_drud, |
| 611 | .ready_msg = check_dr_msg, | 688 | .ready_msg = check_dr_msg, |
| @@ -623,6 +700,8 @@ drfbfin_drfb = { | |||
| 623 | .shortname = "drfbfin", | 700 | .shortname = "drfbfin", |
| 624 | .name = "DR finish on F/B without breaking DR", | 701 | .name = "DR finish on F/B without breaking DR", |
| 625 | 702 | ||
| 703 | .final = true, | ||
| 704 | .is_done = is_solved, | ||
| 626 | .estimate = estimate_drudfin_drud, | 705 | .estimate = estimate_drudfin_drud, |
| 627 | .ready = check_drud, | 706 | .ready = check_drud, |
| 628 | .ready_msg = check_dr_msg, | 707 | .ready_msg = check_dr_msg, |
| @@ -641,6 +720,8 @@ htr_any = { | |||
| 641 | .shortname = "htr", | 720 | .shortname = "htr", |
| 642 | .name = "HTR from DR", | 721 | .name = "HTR from DR", |
| 643 | 722 | ||
| 723 | .final = false, | ||
| 724 | .is_done = check_htr, | ||
| 644 | .estimate = estimate_htr_drud, | 725 | .estimate = estimate_htr_drud, |
| 645 | .ready = check_drud, | 726 | .ready = check_drud, |
| 646 | .ready_msg = check_drany_msg, | 727 | .ready_msg = check_drany_msg, |
| @@ -658,6 +739,8 @@ htr_drud = { | |||
| 658 | .shortname = "htr-drud", | 739 | .shortname = "htr-drud", |
| 659 | .name = "HTR from DR on U/D", | 740 | .name = "HTR from DR on U/D", |
| 660 | 741 | ||
| 742 | .final = false, | ||
| 743 | .is_done = check_htr, | ||
| 661 | .estimate = estimate_htr_drud, | 744 | .estimate = estimate_htr_drud, |
| 662 | .ready = check_drud, | 745 | .ready = check_drud, |
| 663 | .ready_msg = check_dr_msg, | 746 | .ready_msg = check_dr_msg, |
| @@ -675,6 +758,8 @@ htr_drrl = { | |||
| 675 | .shortname = "htr-drrl", | 758 | .shortname = "htr-drrl", |
| 676 | .name = "HTR from DR on R/L", | 759 | .name = "HTR from DR on R/L", |
| 677 | 760 | ||
| 761 | .final = false, | ||
| 762 | .is_done = check_htr, | ||
| 678 | .estimate = estimate_htr_drud, | 763 | .estimate = estimate_htr_drud, |
| 679 | .ready = check_drud, | 764 | .ready = check_drud, |
| 680 | .ready_msg = check_dr_msg, | 765 | .ready_msg = check_dr_msg, |
| @@ -692,6 +777,8 @@ htr_drfb = { | |||
| 692 | .shortname = "htr-drfb", | 777 | .shortname = "htr-drfb", |
| 693 | .name = "HTR from DR on F/B", | 778 | .name = "HTR from DR on F/B", |
| 694 | 779 | ||
| 780 | .final = false, | ||
| 781 | .is_done = check_htr, | ||
| 695 | .estimate = estimate_htr_drud, | 782 | .estimate = estimate_htr_drud, |
| 696 | .ready = check_drud, | 783 | .ready = check_drud, |
| 697 | .ready_msg = check_dr_msg, | 784 | .ready_msg = check_dr_msg, |
| @@ -710,6 +797,8 @@ htrfin_htr = { | |||
| 710 | .shortname = "htrfin", | 797 | .shortname = "htrfin", |
| 711 | .name = "HTR finish without breaking HTR", | 798 | .name = "HTR finish without breaking HTR", |
| 712 | 799 | ||
| 800 | .final = true, | ||
| 801 | .is_done = is_solved, | ||
| 713 | .estimate = estimate_htrfin_htr, | 802 | .estimate = estimate_htrfin_htr, |
| 714 | .ready = check_htr, | 803 | .ready = check_htr, |
| 715 | .ready_msg = check_htr_msg, | 804 | .ready_msg = check_htr_msg, |
| @@ -783,12 +872,89 @@ check_centers(Cube cube) | |||
| 783 | } | 872 | } |
| 784 | 873 | ||
| 785 | static bool | 874 | static bool |
| 875 | check_coany_HTM(Cube cube) | ||
| 876 | { | ||
| 877 | return cube.cofb == 0 || cube.corl == 0 || cube.coud == 0; | ||
| 878 | } | ||
| 879 | |||
| 880 | static bool | ||
| 881 | check_coud_HTM(Cube cube) | ||
| 882 | { | ||
| 883 | return cube.coud == 0; | ||
| 884 | } | ||
| 885 | |||
| 886 | static bool | ||
| 887 | check_coany_URF(Cube cube) | ||
| 888 | { | ||
| 889 | Cube c2, c3; | ||
| 890 | |||
| 891 | c2 = apply_move(y, apply_move(z, cube)); | ||
| 892 | c3 = apply_move(y, apply_move(x, cube)); | ||
| 893 | |||
| 894 | return check_coany_HTM(cube) || | ||
| 895 | check_coany_HTM(c2) || | ||
| 896 | check_coany_HTM(c3); | ||
| 897 | } | ||
| 898 | |||
| 899 | static bool | ||
| 900 | check_coud_URF(Cube cube) | ||
| 901 | { | ||
| 902 | Cube c2, c3; | ||
| 903 | |||
| 904 | c2 = apply_move(z, cube); | ||
| 905 | c3 = apply_move(x, cube); | ||
| 906 | |||
| 907 | return cube.coud == 0 || c2.coud == 0 || c3.coud == 0; | ||
| 908 | } | ||
| 909 | |||
| 910 | static bool | ||
| 911 | check_corners_URF(Cube cube) | ||
| 912 | { | ||
| 913 | Cube c; | ||
| 914 | Trans i; | ||
| 915 | |||
| 916 | for (i = 0; i < NROTATIONS; i++) { | ||
| 917 | c = apply_alg(rotation_alg(i), cube); | ||
| 918 | if (c.cp && c.coud) | ||
| 919 | return true; | ||
| 920 | } | ||
| 921 | |||
| 922 | return false; | ||
| 923 | } | ||
| 924 | |||
| 925 | static bool | ||
| 926 | check_corners_HTM(Cube cube) | ||
| 927 | { | ||
| 928 | return cube.cp == 0 && cube.coud == 0; | ||
| 929 | } | ||
| 930 | |||
| 931 | static bool | ||
| 932 | check_cornershtr(Cube cube) | ||
| 933 | { | ||
| 934 | return coord_cornershtr.index(cube) == 0; | ||
| 935 | } | ||
| 936 | |||
| 937 | static bool | ||
| 938 | check_eoany(Cube cube) | ||
| 939 | { | ||
| 940 | return cube.eofb == 0 || cube.eorl == 0 || cube.eoud == 0; | ||
| 941 | } | ||
| 942 | |||
| 943 | static bool | ||
| 786 | check_eofb(Cube cube) | 944 | check_eofb(Cube cube) |
| 787 | { | 945 | { |
| 788 | return cube.eofb == 0; | 946 | return cube.eofb == 0; |
| 789 | } | 947 | } |
| 790 | 948 | ||
| 791 | static bool | 949 | static bool |
| 950 | check_drany(Cube cube) | ||
| 951 | { | ||
| 952 | return (cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0) || | ||
| 953 | (cube.eorl == 0 && cube.eoud == 0 && cube.cofb == 0) || | ||
| 954 | (cube.eoud == 0 && cube.eofb == 0 && cube.corl == 0); | ||
| 955 | } | ||
| 956 | |||
| 957 | static bool | ||
| 792 | check_drud(Cube cube) | 958 | check_drud(Cube cube) |
| 793 | { | 959 | { |
| 794 | return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; | 960 | return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; |
| @@ -801,265 +967,283 @@ check_htr(Cube cube) | |||
| 801 | } | 967 | } |
| 802 | 968 | ||
| 803 | static int | 969 | static int |
| 804 | estimate_eoany_HTM(EstimateData *ed) | 970 | estimate_eoany_HTM(DfsArg *arg) |
| 805 | { | 971 | { |
| 806 | int r1, r2, r3; | 972 | int r1, r2, r3; |
| 807 | 973 | ||
| 808 | r1 = ptableval(&pd_eofb_HTM, ed->cube); | 974 | r1 = ptableval(&pd_eofb_HTM, arg->cube); |
| 809 | r2 = ptableval(&pd_eofb_HTM, apply_trans(ur, ed->cube)); | 975 | r2 = ptableval(&pd_eofb_HTM, apply_trans(ur, arg->cube)); |
| 810 | r3 = ptableval(&pd_eofb_HTM, apply_trans(fd, ed->cube)); | 976 | r3 = ptableval(&pd_eofb_HTM, apply_trans(fd, arg->cube)); |
| 811 | 977 | ||
| 812 | return MIN(r1, MIN(r2, r3)); | 978 | return MIN(r1, MIN(r2, r3)); |
| 813 | } | 979 | } |
| 814 | 980 | ||
| 815 | static int | 981 | static int |
| 816 | estimate_eofb_HTM(EstimateData *ed) | 982 | estimate_eofb_HTM(DfsArg *arg) |
| 817 | { | 983 | { |
| 818 | return ptableval(&pd_eofb_HTM, ed->cube); | 984 | return ptableval(&pd_eofb_HTM, arg->cube); |
| 819 | } | 985 | } |
| 820 | 986 | ||
| 821 | static int | 987 | static int |
| 822 | estimate_coany_HTM(EstimateData *ed) | 988 | estimate_coany_HTM(DfsArg *arg) |
| 823 | { | 989 | { |
| 824 | int r1, r2, r3; | 990 | int r1, r2, r3; |
| 825 | 991 | ||
| 826 | r1 = ptableval(&pd_coud_HTM, ed->cube); | 992 | r1 = ptableval(&pd_coud_HTM, arg->cube); |
| 827 | r2 = ptableval(&pd_coud_HTM, apply_trans(rf, ed->cube)); | 993 | r2 = ptableval(&pd_coud_HTM, apply_trans(rf, arg->cube)); |
| 828 | r3 = ptableval(&pd_coud_HTM, apply_trans(fd, ed->cube)); | 994 | r3 = ptableval(&pd_coud_HTM, apply_trans(fd, arg->cube)); |
| 829 | 995 | ||
| 830 | return MIN(r1, MIN(r2, r3)); | 996 | return MIN(r1, MIN(r2, r3)); |
| 831 | } | 997 | } |
| 832 | 998 | ||
| 833 | static int | 999 | static int |
| 834 | estimate_coud_HTM(EstimateData *ed) | 1000 | estimate_coud_HTM(DfsArg *arg) |
| 835 | { | 1001 | { |
| 836 | return ptableval(&pd_coud_HTM, ed->cube); | 1002 | return ptableval(&pd_coud_HTM, arg->cube); |
| 837 | } | 1003 | } |
| 838 | 1004 | ||
| 839 | static int | 1005 | static int |
| 840 | estimate_coany_URF(EstimateData *ed) | 1006 | estimate_coany_URF(DfsArg *arg) |
| 841 | { | 1007 | { |
| 842 | int r1, r2, r3; | 1008 | int r1, r2, r3; |
| 843 | EstimateData *ed2, *ed3; | 1009 | Cube c; |
| 844 | 1010 | ||
| 845 | ed2 = malloc(sizeof(EstimateData)); | 1011 | c = arg->cube; |
| 846 | ed3 = malloc(sizeof(EstimateData)); | ||
| 847 | 1012 | ||
| 848 | ed2->cube = apply_trans(rf, ed->cube); | 1013 | r1 = estimate_coud_URF(arg); |
| 849 | ed2->target = ed->target; | 1014 | arg->cube = apply_trans(rf, c); |
| 1015 | r2 = estimate_coud_URF(arg); | ||
| 1016 | arg->cube = apply_trans(fd, c); | ||
| 1017 | r3 = estimate_coud_URF(arg); | ||
| 850 | 1018 | ||
| 851 | ed3->cube = apply_trans(fd, ed->cube); | 1019 | arg->cube = c; |
| 852 | ed3->target = ed->target; | ||
| 853 | |||
| 854 | r1 = estimate_coud_URF(ed); | ||
| 855 | r2 = estimate_coud_URF(ed2); | ||
| 856 | r3 = estimate_coud_URF(ed3); | ||
| 857 | |||
| 858 | free(ed2); | ||
| 859 | free(ed3); | ||
| 860 | 1020 | ||
| 861 | return MIN(r1, MIN(r2, r3)); | 1021 | return MIN(r1, MIN(r2, r3)); |
| 862 | } | 1022 | } |
| 863 | 1023 | ||
| 864 | static int | 1024 | static int |
| 865 | estimate_coud_URF(EstimateData *ed) | 1025 | estimate_coud_URF(DfsArg *arg) |
| 866 | { | 1026 | { |
| 867 | /* TODO: I can improve this by checking first the orientation of | 1027 | /* TODO: I can improve this by checking first the orientation of |
| 868 | * the corner in DBL and use that as a reference */ | 1028 | * the corner in DBL and use that as a reference */ |
| 869 | 1029 | ||
| 870 | EstimateData *ed2, *ed3; | 1030 | Cube c; |
| 871 | |||
| 872 | ed2 = malloc(sizeof(EstimateData)); | ||
| 873 | ed2->cube = apply_move(z, ed->cube); | ||
| 874 | ed2->target = ed->target; | ||
| 875 | 1031 | ||
| 876 | ed3 = malloc(sizeof(EstimateData)); | 1032 | c = arg->cube; |
| 877 | ed3->cube = apply_move(x, ed->cube); | ||
| 878 | ed3->target = ed->target; | ||
| 879 | 1033 | ||
| 880 | int ud = estimate_coud_HTM(ed); | 1034 | int ud = estimate_coud_HTM(arg); |
| 881 | int rl = estimate_coud_HTM(ed2); | 1035 | arg->cube = apply_move(z, c); |
| 882 | int fb = estimate_coud_HTM(ed3); | 1036 | int rl = estimate_coud_HTM(arg); |
| 1037 | arg->cube = apply_move(x, c); | ||
| 1038 | int fb = estimate_coud_HTM(arg); | ||
| 883 | 1039 | ||
| 884 | free(ed2); | 1040 | arg->cube = c; |
| 885 | free(ed3); | ||
| 886 | 1041 | ||
| 887 | return MIN(ud, MIN(rl, fb)); | 1042 | return MIN(ud, MIN(rl, fb)); |
| 888 | } | 1043 | } |
| 889 | 1044 | ||
| 890 | static int | 1045 | static int |
| 891 | estimate_corners_HTM(EstimateData *ed) | 1046 | estimate_corners_HTM(DfsArg *arg) |
| 892 | { | 1047 | { |
| 893 | return ptableval(&pd_corners_HTM, ed->cube); | 1048 | return ptableval(&pd_corners_HTM, arg->cube); |
| 894 | } | 1049 | } |
| 895 | 1050 | ||
| 896 | static int | 1051 | static int |
| 897 | estimate_cornershtr_HTM(EstimateData *ed) | 1052 | estimate_cornershtr_HTM(DfsArg *arg) |
| 898 | { | 1053 | { |
| 899 | return ptableval(&pd_cornershtr_HTM, ed->cube); | 1054 | return ptableval(&pd_cornershtr_HTM, arg->cube); |
| 900 | } | 1055 | } |
| 901 | 1056 | ||
| 902 | static int | 1057 | static int |
| 903 | estimate_cornershtr_URF(EstimateData *ed) | 1058 | estimate_cornershtr_URF(DfsArg *arg) |
| 904 | { | 1059 | { |
| 905 | /* TODO: I can improve this by checking first the corner in DBL | 1060 | /* TODO: I can improve this by checking first the corner in DBL |
| 906 | * and use that as a reference */ | 1061 | * and use that as a reference */ |
| 907 | 1062 | ||
| 908 | int c, ret = 15; | 1063 | int ret; |
| 1064 | Cube c; | ||
| 909 | Trans i; | 1065 | Trans i; |
| 910 | 1066 | ||
| 1067 | c = arg->cube; | ||
| 1068 | ret = 15; | ||
| 1069 | |||
| 911 | for (i = 0; i < NROTATIONS; i++) { | 1070 | for (i = 0; i < NROTATIONS; i++) { |
| 912 | ed->cube = apply_alg(rotation_alg(i), ed->cube); | 1071 | arg->cube = apply_alg(rotation_alg(i), c); |
| 913 | c = estimate_cornershtr_HTM(ed); | 1072 | ret = MIN(ret, estimate_cornershtr_HTM(arg)); |
| 914 | ret = MIN(ret, c); | ||
| 915 | } | 1073 | } |
| 916 | 1074 | ||
| 1075 | arg->cube = c; | ||
| 1076 | |||
| 917 | return ret; | 1077 | return ret; |
| 918 | } | 1078 | } |
| 919 | 1079 | ||
| 920 | static int | 1080 | static int |
| 921 | estimate_corners_URF(EstimateData *ed) | 1081 | estimate_corners_URF(DfsArg *arg) |
| 922 | { | 1082 | { |
| 923 | /* TODO: I can improve this by checking first the corner in DBL | 1083 | /* TODO: I can improve this by checking first the corner in DBL |
| 924 | * and use that as a reference */ | 1084 | * and use that as a reference */ |
| 925 | 1085 | ||
| 926 | int c, ret = 15; | 1086 | int ret; |
| 1087 | Cube c; | ||
| 927 | Trans i; | 1088 | Trans i; |
| 928 | 1089 | ||
| 1090 | c = arg->cube; | ||
| 1091 | ret = 15; | ||
| 1092 | |||
| 929 | for (i = 0; i < NROTATIONS; i++) { | 1093 | for (i = 0; i < NROTATIONS; i++) { |
| 930 | ed->cube = apply_alg(rotation_alg(i), ed->cube); | 1094 | arg->cube = apply_alg(rotation_alg(i), c); |
| 931 | c = estimate_corners_HTM(ed); | 1095 | ret = MIN(ret, estimate_corners_HTM(arg)); |
| 932 | ret = MIN(ret, c); | ||
| 933 | } | 1096 | } |
| 934 | 1097 | ||
| 1098 | arg->cube = c; | ||
| 1099 | |||
| 935 | return ret; | 1100 | return ret; |
| 936 | } | 1101 | } |
| 937 | 1102 | ||
| 938 | static int | 1103 | static int |
| 939 | estimate_drany_HTM(EstimateData *ed) | 1104 | estimate_drany_HTM(DfsArg *arg) |
| 940 | { | 1105 | { |
| 941 | int r1, r2, r3; | 1106 | int r1, r2, r3; |
| 942 | 1107 | ||
| 943 | r1 = ptableval(&pd_drud_sym16_HTM, ed->cube); | 1108 | r1 = ptableval(&pd_drud_sym16_HTM, arg->cube); |
| 944 | r2 = ptableval(&pd_drud_sym16_HTM, apply_trans(rf, ed->cube)); | 1109 | r2 = ptableval(&pd_drud_sym16_HTM, apply_trans(rf, arg->cube)); |
| 945 | r3 = ptableval(&pd_drud_sym16_HTM, apply_trans(fd, ed->cube)); | 1110 | r3 = ptableval(&pd_drud_sym16_HTM, apply_trans(fd, arg->cube)); |
| 946 | 1111 | ||
| 947 | return MIN(r1, MIN(r2, r3)); | 1112 | return MIN(r1, MIN(r2, r3)); |
| 948 | } | 1113 | } |
| 949 | 1114 | ||
| 950 | static int | 1115 | static int |
| 951 | estimate_drud_HTM(EstimateData *ed) | 1116 | estimate_drud_HTM(DfsArg *arg) |
| 952 | { | 1117 | { |
| 953 | return ptableval(&pd_drud_sym16_HTM, ed->cube); | 1118 | return ptableval(&pd_drud_sym16_HTM, arg->cube); |
| 954 | } | 1119 | } |
| 955 | 1120 | ||
| 956 | static int | 1121 | static int |
| 957 | estimate_drud_eofb(EstimateData *ed) | 1122 | estimate_drud_eofb(DfsArg *arg) |
| 958 | { | 1123 | { |
| 959 | return ptableval(&pd_drud_eofb, ed->cube); | 1124 | return ptableval(&pd_drud_eofb, arg->cube); |
| 960 | } | 1125 | } |
| 961 | 1126 | ||
| 962 | static int | 1127 | static int |
| 963 | estimate_dr_eofb(EstimateData *ed) | 1128 | estimate_dr_eofb(DfsArg *arg) |
| 964 | { | 1129 | { |
| 965 | int r1, r2; | 1130 | int r1, r2; |
| 966 | 1131 | ||
| 967 | r1 = ptableval(&pd_drud_eofb, ed->cube); | 1132 | r1 = ptableval(&pd_drud_eofb, arg->cube); |
| 968 | r2 = ptableval(&pd_drud_eofb, apply_trans(rf, ed->cube)); | 1133 | r2 = ptableval(&pd_drud_eofb, apply_trans(rf, arg->cube)); |
| 969 | 1134 | ||
| 970 | return MIN(r1, r2); | 1135 | return MIN(r1, r2); |
| 971 | } | 1136 | } |
| 972 | 1137 | ||
| 973 | static int | 1138 | static int |
| 974 | estimate_drudfin_drud(EstimateData *ed) | 1139 | estimate_drudfin_drud(DfsArg *arg) |
| 975 | { | 1140 | { |
| 976 | int val = ptableval(&pd_drudfin_noE_sym16_drud, ed->cube); | 1141 | int val = ptableval(&pd_drudfin_noE_sym16_drud, arg->cube); |
| 977 | 1142 | ||
| 978 | if (val != 0) | 1143 | if (val != 0) |
| 979 | return val; | 1144 | return val; |
| 980 | 1145 | ||
| 981 | return ed->cube.epose % 24 == 0 ? 0 : 1; | 1146 | return arg->cube.epose % 24 == 0 ? 0 : 1; |
| 982 | } | 1147 | } |
| 983 | 1148 | ||
| 984 | static int | 1149 | static int |
| 985 | estimate_htr_drud(EstimateData *ed) | 1150 | estimate_htr_drud(DfsArg *arg) |
| 986 | { | 1151 | { |
| 987 | return ptableval(&pd_htr_drud, ed->cube); | 1152 | return ptableval(&pd_htr_drud, arg->cube); |
| 988 | } | 1153 | } |
| 989 | 1154 | ||
| 990 | static int | 1155 | static int |
| 991 | estimate_htrfin_htr(EstimateData *ed) | 1156 | estimate_htrfin_htr(DfsArg *arg) |
| 992 | { | 1157 | { |
| 993 | return ptableval(&pd_htrfin_htr, ed->cube); | 1158 | return ptableval(&pd_htrfin_htr, arg->cube); |
| 994 | } | 1159 | } |
| 995 | 1160 | ||
| 996 | static int | 1161 | static int |
| 997 | estimate_optimal_HTM(EstimateData *ed) | 1162 | estimate_optimal_HTM(DfsArg *arg) |
| 998 | { | 1163 | { |
| 999 | int ret = -1; | 1164 | int target, ret; |
| 1000 | Move lbase; | 1165 | Move lbase; |
| 1001 | Cube cubeaux, inv; | 1166 | Cube aux; |
| 1002 | 1167 | ||
| 1003 | ed->li->corners = ptableval(&pd_corners_HTM, ed->cube); | 1168 | target = arg->d - arg->current_alg->len; |
| 1004 | UPDATECHECKSTOP(ret, ed->li->corners, ed->target); | 1169 | ret = -1; |
| 1170 | arg->inverse = (Cube){0}; | ||
| 1171 | arg->badmovesinv = 0; | ||
| 1172 | arg->badmoves = 0; | ||
| 1005 | 1173 | ||
| 1006 | ed->li->normal_ud = ptableval(&pd_khuge_HTM, ed->cube); | 1174 | arg->ed->corners = ptableval(&pd_corners_HTM, arg->cube); |
| 1007 | UPDATECHECKSTOP(ret, ed->li->normal_ud, ed->target); | 1175 | UPDATECHECKSTOP(ret, arg->ed->corners, target); |
| 1008 | 1176 | ||
| 1009 | cubeaux = apply_trans(fd, ed->cube); | 1177 | arg->ed->normal_ud = ptableval(&pd_khuge_HTM, arg->cube); |
| 1010 | ed->li->normal_fb = ptableval(&pd_khuge_HTM, cubeaux); | 1178 | UPDATECHECKSTOP(ret, arg->ed->normal_ud, target); |
| 1011 | UPDATECHECKSTOP(ret, ed->li->normal_fb, ed->target); | 1179 | if (arg->ed->normal_ud == target) { |
| 1180 | arg->badmovesinv |= (1<<U) | (1<<U2) | (1<<U3) | | ||
| 1181 | (1<<D) | (1<<D2) | (1<<D3); | ||
| 1182 | } | ||
| 1012 | 1183 | ||
| 1013 | cubeaux = apply_trans(rf, ed->cube); | 1184 | aux = apply_trans(fd, arg->cube); |
| 1014 | ed->li->normal_rl = ptableval(&pd_khuge_HTM, cubeaux); | 1185 | arg->ed->normal_fb = ptableval(&pd_khuge_HTM, aux); |
| 1015 | UPDATECHECKSTOP(ret, ed->li->normal_rl, ed->target); | 1186 | UPDATECHECKSTOP(ret, arg->ed->normal_fb, target); |
| 1187 | if (arg->ed->normal_fb == target) { | ||
| 1188 | arg->badmovesinv |= (1<<F) | (1<<F2) | (1<<F3) | | ||
| 1189 | (1<<B) | (1<<B2) | (1<<B3); | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | aux = apply_trans(rf, arg->cube); | ||
| 1193 | arg->ed->normal_rl = ptableval(&pd_khuge_HTM, aux); | ||
| 1194 | UPDATECHECKSTOP(ret, arg->ed->normal_rl, target); | ||
| 1195 | if (arg->ed->normal_rl == target) { | ||
| 1196 | arg->badmovesinv |= (1<<R) | (1<<R2) | (1<<R3) | | ||
| 1197 | (1<<L) | (1<<L2) | (1<<L3); | ||
| 1198 | } | ||
| 1016 | 1199 | ||
| 1017 | if (ret == 0) | 1200 | if (ret == 0) |
| 1018 | return ret; | 1201 | return ret; |
| 1019 | 1202 | ||
| 1020 | if (ed->li->normal_ud == ed->li->normal_fb && | 1203 | if (arg->ed->normal_ud == arg->ed->normal_fb && |
| 1021 | ed->li->normal_fb == ed->li->normal_rl) | 1204 | arg->ed->normal_fb == arg->ed->normal_rl) |
| 1022 | UPDATECHECKSTOP(ret, ed->li->normal_ud + 1, ed->target); | 1205 | UPDATECHECKSTOP(ret, arg->ed->normal_ud + 1, target); |
| 1023 | 1206 | ||
| 1024 | /* TODO: avoid computation of inverse if unnecessary */ | 1207 | /* TODO: avoid computation of inverse if unnecessary */ |
| 1025 | lbase = base_move(ed->lastmove); | 1208 | lbase = base_move(arg->last1); |
| 1026 | inv = inverse_cube(ed->cube); | 1209 | arg->inverse = inverse_cube(arg->cube); |
| 1027 | 1210 | ||
| 1028 | if ((lbase != U && lbase != D) || | 1211 | if ((lbase != U && lbase != D) || (arg->ed->inverse_ud == -1)) { |
| 1029 | (ed->li->inverse_ud == -1)) { | 1212 | arg->ed->inverse_ud = ptableval(&pd_khuge_HTM, arg->inverse); |
| 1030 | ed->li->inverse_ud = ptableval(&pd_khuge_HTM, inv); | ||
| 1031 | } | 1213 | } |
| 1032 | UPDATECHECKSTOP(ret, ed->li->inverse_ud, ed->target); | 1214 | UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); |
| 1033 | 1215 | ||
| 1034 | if ((lbase != F && lbase != B) || | 1216 | if ((lbase != F && lbase != B) || (arg->ed->inverse_fb == -1)) { |
| 1035 | (ed->li->inverse_fb == -1)) { | 1217 | aux = apply_trans(fd, arg->inverse); |
| 1036 | cubeaux = apply_trans(fd, inv); | 1218 | arg->ed->inverse_fb = ptableval(&pd_khuge_HTM, aux); |
| 1037 | ed->li->inverse_fb = ptableval(&pd_khuge_HTM, cubeaux); | ||
| 1038 | } | 1219 | } |
| 1039 | UPDATECHECKSTOP(ret, ed->li->inverse_fb, ed->target); | 1220 | UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); |
| 1040 | 1221 | ||
| 1041 | if ((lbase != R && lbase != L) || | 1222 | if ((lbase != R && lbase != L) || (arg->ed->inverse_rl == -1)) { |
| 1042 | (ed->li->inverse_rl == -1)) { | 1223 | aux = apply_trans(rf, arg->inverse); |
| 1043 | cubeaux = apply_trans(rf, inv); | 1224 | arg->ed->inverse_rl = ptableval(&pd_khuge_HTM, aux); |
| 1044 | ed->li->inverse_rl = ptableval(&pd_khuge_HTM, cubeaux); | ||
| 1045 | } | 1225 | } |
| 1046 | UPDATECHECKSTOP(ret, ed->li->inverse_rl, ed->target); | 1226 | UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); |
| 1047 | 1227 | ||
| 1048 | if (ed->li->inverse_ud == ed->li->inverse_fb && | 1228 | if (arg->ed->inverse_ud == arg->ed->inverse_fb && |
| 1049 | ed->li->inverse_fb == ed->li->inverse_rl) | 1229 | arg->ed->inverse_fb == arg->ed->inverse_rl) { |
| 1050 | UPDATECHECKSTOP(ret, ed->li->inverse_ud + 1, ed->target); | 1230 | UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target); |
| 1231 | } | ||
| 1051 | 1232 | ||
| 1052 | if (ed->li->inverse_ud == ed->target) | 1233 | if (arg->ed->inverse_ud == target) { |
| 1053 | ed->movebitmask |= (1<<U) | (1<<U2) | (1<<U3) | | 1234 | arg->badmoves |= (1<<U) | (1<<U2) | (1<<U3) | |
| 1054 | (1<<D) | (1<<D2) | (1<<D3); | 1235 | (1<<D) | (1<<D2) | (1<<D3); |
| 1055 | if (ed->li->inverse_fb == ed->target) | 1236 | } |
| 1056 | ed->movebitmask |= (1<<F) | (1<<F2) | (1<<F3) | | 1237 | if (arg->ed->inverse_fb == target) { |
| 1057 | (1<<B) | (1<<B2) | (1<<B3); | 1238 | arg->badmoves |= (1<<F) | (1<<F2) | (1<<F3) | |
| 1058 | if (ed->li->inverse_rl == ed->target) | 1239 | (1<<B) | (1<<B2) | (1<<B3); |
| 1059 | ed->movebitmask |= (1<<R) | (1<<R2) | (1<<R3) | | 1240 | } |
| 1060 | (1<<L) | (1<<L2) | (1<<L3); | 1241 | if (arg->ed->inverse_rl == target) { |
| 1242 | arg->badmoves |= (1<<R) | (1<<R2) | (1<<R3) | | ||
| 1243 | (1<<L) | (1<<L2) | (1<<L3); | ||
| 1244 | } | ||
| 1061 | 1245 | ||
| 1062 | return ret; | 1246 | return arg->ed->oldret = ret; |
| 1063 | } | 1247 | } |
| 1064 | 1248 | ||
| 1065 | static bool | 1249 | static bool |
| @@ -1120,15 +1304,36 @@ detect_pretrans_drud(Cube cube) | |||
| 1120 | /* Public functions **********************************************************/ | 1304 | /* Public functions **********************************************************/ |
| 1121 | 1305 | ||
| 1122 | void | 1306 | void |
| 1123 | free_localinfo(LocalInfo *li) | 1307 | copy_estimatedata(EstimateData *src, EstimateData *dst) |
| 1124 | { | 1308 | { |
| 1125 | free(li); | 1309 | dst->corners = src->corners; |
| 1310 | dst->normal_ud = src->normal_ud; | ||
| 1311 | dst->normal_fb = src->normal_fb; | ||
| 1312 | dst->normal_rl = src->normal_rl; | ||
| 1313 | dst->inverse_ud = src->inverse_ud; | ||
| 1314 | dst->inverse_fb = src->inverse_fb; | ||
| 1315 | dst->inverse_rl = src->inverse_rl; | ||
| 1316 | dst->oldret = src->oldret; | ||
| 1126 | } | 1317 | } |
| 1127 | 1318 | ||
| 1128 | LocalInfo * | 1319 | void |
| 1129 | new_localinfo() | 1320 | free_estimatedata(EstimateData *ed) |
| 1130 | { | 1321 | { |
| 1131 | LocalInfo *ret = malloc(sizeof(LocalInfo)); | 1322 | free(ed); |
| 1323 | } | ||
| 1324 | |||
| 1325 | void | ||
| 1326 | invert_estimatedata(EstimateData *ed) | ||
| 1327 | { | ||
| 1328 | swap(&(ed->normal_ud), &(ed->inverse_ud)); | ||
| 1329 | swap(&(ed->normal_fb), &(ed->inverse_fb)); | ||
| 1330 | swap(&(ed->normal_rl), &(ed->inverse_rl)); | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | EstimateData * | ||
| 1334 | new_estimatedata() | ||
| 1335 | { | ||
| 1336 | EstimateData *ret = malloc(sizeof(EstimateData)); | ||
| 1132 | 1337 | ||
| 1133 | ret->corners = -1; | 1338 | ret->corners = -1; |
| 1134 | ret->normal_ud = -1; | 1339 | ret->normal_ud = -1; |
| @@ -1137,16 +1342,22 @@ new_localinfo() | |||
| 1137 | ret->inverse_ud = -1; | 1342 | ret->inverse_ud = -1; |
| 1138 | ret->inverse_fb = -1; | 1343 | ret->inverse_fb = -1; |
| 1139 | ret->inverse_rl = -1; | 1344 | ret->inverse_rl = -1; |
| 1140 | ret->prev_ret = -1; | 1345 | ret->oldret = -1; |
| 1141 | 1346 | ||
| 1142 | return ret; | 1347 | return ret; |
| 1143 | } | 1348 | } |
| 1144 | 1349 | ||
| 1145 | void | 1350 | void |
| 1146 | prepare_step(Step *step, int nthreads) | 1351 | prepare_step(Step *step, SolveOptions *opts) |
| 1147 | { | 1352 | { |
| 1148 | int i; | 1353 | int i; |
| 1149 | 1354 | ||
| 1355 | if (step->final && opts->can_niss) { | ||
| 1356 | opts->can_niss = false; | ||
| 1357 | fprintf(stderr, "Step if final, niss not used" | ||
| 1358 | "(-n ignored)\n"); | ||
| 1359 | } | ||
| 1360 | |||
| 1150 | for (i = 0; i < step->ntables; i++) | 1361 | for (i = 0; i < step->ntables; i++) |
| 1151 | genptable(step->tables[i], nthreads); | 1362 | genptable(step->tables[i], opts->nthreads); |
| 1152 | } | 1363 | } |
diff --git a/src/steps.h b/src/steps.h index e145c64..a55a101 100644 --- a/src/steps.h +++ b/src/steps.h | |||
| @@ -7,8 +7,10 @@ | |||
| 7 | 7 | ||
| 8 | extern Step * steps[NSTEPS]; | 8 | extern Step * steps[NSTEPS]; |
| 9 | 9 | ||
| 10 | void free_localinfo(LocalInfo *li); | 10 | void copy_estimatedata(EstimateData *s, EstimateData *d); |
| 11 | LocalInfo * new_localinfo(); | 11 | void free_estimatedata(EstimateData *ed); |
| 12 | void prepare_step(Step *step, int nthreads); | 12 | void invert_estimatedata(EstimateData *ed); |
| 13 | EstimateData * new_estimatedata(); | ||
| 14 | void prepare_step(Step *step, SolveOptions *opts); | ||
| 13 | 15 | ||
| 14 | #endif | 16 | #endif |
diff --git a/src/utils.c b/src/utils.c index 1c829c4..e0d3268 100644 --- a/src/utils.c +++ b/src/utils.c | |||
| @@ -272,7 +272,17 @@ swap(int *a, int *b) | |||
| 272 | int aux; | 272 | int aux; |
| 273 | 273 | ||
| 274 | aux = *a; | 274 | aux = *a; |
| 275 | *a = *b; | 275 | *a = *b; |
| 276 | *b = aux; | 276 | *b = aux; |
| 277 | } | ||
| 278 | |||
| 279 | void | ||
| 280 | swapu64(uint64_t *a, uint64_t *b) | ||
| 281 | { | ||
| 282 | uint64_t aux; | ||
| 283 | |||
| 284 | aux = *a; | ||
| 285 | *a = *b; | ||
| 286 | *b = aux; | ||
| 277 | } | 287 | } |
| 278 | 288 | ||
diff --git a/src/utils.h b/src/utils.h index 80c33ae..9ba228d 100644 --- a/src/utils.h +++ b/src/utils.h | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | #define UTILS_H | 2 | #define UTILS_H |
| 3 | 3 | ||
| 4 | #include <stdbool.h> | 4 | #include <stdbool.h> |
| 5 | #include <stdint.h> | ||
| 5 | #include <stdlib.h> | 6 | #include <stdlib.h> |
| 6 | #include <string.h> | 7 | #include <string.h> |
| 7 | 8 | ||
| @@ -37,5 +38,6 @@ int powint(int a, int b); | |||
| 37 | int subset_to_index(int *a, int n, int k); | 38 | int subset_to_index(int *a, int n, int k); |
| 38 | void sum_arrays_mod(int *src, int *dst, int n, int m); | 39 | void sum_arrays_mod(int *src, int *dst, int n, int m); |
| 39 | void swap(int *a, int *b); | 40 | void swap(int *a, int *b); |
| 41 | void swapu64(uint64_t *a, uint64_t *b); | ||
| 40 | 42 | ||
| 41 | #endif | 43 | #endif |
