nissy-fmc

A Rubik's cube FMC assistant
git clone https://git.tronto.net/nissy-fmc
Download | Log | Files | Refs | README | LICENSE

commit 1215648b1ba3c592bd9d97b871349673d1702e44
parent 296f35b7ed4ea3177c520f28176f44d6ad47d76d
Author: Sebastiano Tronto <sebastiano.tronto@gmail.com>
Date:   Mon, 13 Dec 2021 20:40:18 +0100

Faster optimal solver.
This is a pretty big one, but unfortunately performance only improved by about 5%.
I implemented one of the main ideas of nxopt, that is switching to the
inverse scramble on the fly if it gives a lower branching factor.
On the one hand it makes sense that it does not have such a huge impact, since
it only rarely happens that we do have a lower branching factor on inverse, but
on the other hand I am quite sad that the improvement is barely noticeable :-(
Maybe the problem is that I have introduced a lot of new overhead and I can improve
that in the future. Or maybe I am just overlooking something stupid.

Diffstat:
MMakefile | 2+-
MTODO.md | 1+
Anissy | 0
Anissy-2.0beta7.tar.gz | 0
Mnissy.exe | 0
Msrc/alg.c | 32++++++++++++++++++++++++++++++++
Msrc/alg.h | 2++
Msrc/cubetypes.h | 32++++++++++++++------------------
Msrc/solve.c | 318+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/steps.c | 507++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/steps.h | 8+++++---
Msrc/utils.c | 14++++++++++++--
Msrc/utils.h | 2++
13 files changed, 624 insertions(+), 294 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,6 +1,6 @@ # See LICENSE file for copyright and license details. -VERSION = 2.0beta6 +VERSION = 2.0beta7 PREFIX = /usr/local MANPREFIX = ${PREFIX}/share/man diff --git a/TODO.md b/TODO.md @@ -28,6 +28,7 @@ It's more of a personal reminder than anything else. * solve should try up to a small bound without loading the large pruning table * drfin for HTR scrambles should try all 3 axis and pick the best solutions; in general every step that automatically detects orientation should do this +* for solve -v, print certain info like average branching value ### New features * cleanup: translate an alg to the standard HTM moveset + reorient at the end diff --git a/nissy b/nissy Binary files differ. diff --git a/nissy-2.0beta7.tar.gz b/nissy-2.0beta7.tar.gz Binary files differ. diff --git a/nissy.exe b/nissy.exe Binary files differ. diff --git a/src/alg.c b/src/alg.c @@ -373,3 +373,35 @@ realloc_alg(Alg *alg, int n) alg->allocated = n; } +void +swapmove(Move *m1, Move *m2) +{ + Move aux; + + aux = *m1; + *m1 = *m2; + *m2 = aux; +} + +void +unniss(Alg *alg) +{ + int i; + Alg *aux; + + aux = new_alg(""); + + for (i = 0; i < alg->len; i++) + if (!alg->inv[i]) + append_move(aux, alg->move[i], false); + + for (i = alg->len-1; i >= 0; i--) + if (alg->inv[i]) + append_move(aux, inverse_move(alg->move[i]), false); + + for (i = 0; i < alg->len; i++) { + alg->move[i] = aux->move[i]; + alg->inv[i] = false; + } + free(aux); +} diff --git a/src/alg.h b/src/alg.h @@ -30,6 +30,8 @@ AlgList * new_alglist(); Alg * on_inverse(Alg *alg); void print_alg(Alg *alg, bool l); void print_alglist(AlgList *al, bool l); +void swapmove(Move *m1, Move *m2); +void unniss(Alg *alg); #endif diff --git a/src/cubetypes.h b/src/cubetypes.h @@ -81,9 +81,8 @@ typedef struct commandargs CommandArgs; typedef struct coordinate Coordinate; typedef struct cube Cube; typedef struct cubearray CubeArray; -typedef struct dfsdata DfsData; +typedef struct dfsarg DfsArg; typedef struct estimatedata EstimateData; -typedef struct localinfo LocalInfo; typedef struct piecefilter PieceFilter; typedef struct prunedata PruneData; typedef struct solveoptions SolveOptions; @@ -94,7 +93,7 @@ typedef struct threaddatagenpt ThreadDataGenpt; typedef Cube (*AntiIndexer) (uint64_t); typedef bool (*Checker) (Cube); -typedef int (*Estimator) (EstimateData *); +typedef int (*Estimator) (DfsArg *); typedef bool (*Validator) (Alg *); typedef void (*Exec) (CommandArgs *); typedef uint64_t (*Indexer) (Cube); @@ -198,36 +197,31 @@ cubearray }; struct -dfsdata +dfsarg { + Step * step; + SolveOptions * opts; + Cube cube; + Cube inverse; int d; - int m; - int lb; + uint64_t badmoves; + uint64_t badmovesinv; bool niss; Move last1; Move last2; + Move last1inv; + Move last2inv; EstimateData * ed; AlgList * sols; pthread_mutex_t * sols_mutex; Alg * current_alg; Move * sorted_moves; int * move_position; - uint8_t * visited; }; struct estimatedata { - Cube cube; - int target; - Move lastmove; - uint64_t movebitmask; - LocalInfo * li; -}; - -struct -localinfo -{ int corners; int normal_ud; int normal_fb; @@ -235,7 +229,7 @@ localinfo int inverse_ud; int inverse_fb; int inverse_rl; - int prev_ret; + int oldret; }; struct @@ -284,6 +278,8 @@ step { char * shortname; char * name; + bool final; + Checker is_done; Estimator estimate; Checker ready; char * ready_msg; diff --git a/src/solve.c b/src/solve.c @@ -2,155 +2,208 @@ /* Local functions ***********************************************************/ -static bool allowed_next(Move move, DfsData *dd, uint64_t mm); -static void dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd); -static void dfs_branch(Cube c, Step *s, SolveOptions *os, DfsData *dd); -static bool dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd); -static void dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd); -static bool dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd); +static bool allowed_next(Move move, DfsArg *arg); +static bool cancel_niss(DfsArg *arg); +static void copy_dfsarg(DfsArg *src, DfsArg *dst); +static void dfs(DfsArg *arg); +static void dfs_branch(DfsArg *arg); +static bool dfs_check_solved(DfsArg *arg); +static bool dfs_switch_final(DfsArg *arg); +static void dfs_niss(DfsArg *arg); +static bool dfs_stop(DfsArg *arg); static void * instance_thread(void *arg); +static void invert_branch(DfsArg *arg); static void multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d); +static bool niss_makes_sense(DfsArg *arg); /* Local functions ***********************************************************/ static bool -allowed_next(Move move, DfsData *dd, uint64_t mm) +allowed_next(Move m, DfsArg *arg) { - if ((1 << move) & mm) + if ((1 << m) & arg->badmoves) return false; - if (!possible_next(dd->last2, dd->last1, move)) + if (!possible_next(arg->last2, arg->last1, m)) return false; - if (commute(dd->last1, move)) - return dd->move_position[dd->last1] < dd->move_position[move]; + if (commute(arg->last1, m)) + return arg->move_position[arg->last1] < arg->move_position[m]; return true; } +static bool +cancel_niss(DfsArg *arg) +{ + return !possible_next(arg->last2, arg->last1, arg->last1inv) && + !(commute(arg->last1inv, arg->last2inv) && + arg->last2inv != NULLMOVE && + possible_next(arg->last2, arg->last1, arg->last2inv)); +} + +static void +copy_dfsarg(DfsArg *src, DfsArg *dst) +{ + dst->step = src->step; + dst->opts = src->opts; + dst->cube = src->cube; + dst->inverse = src->inverse; + dst->d = src->d; + dst->badmoves = src->badmoves; + dst->badmovesinv = src->badmovesinv; + dst->niss = src->niss; + dst->last1 = src->last1; + dst->last2 = src->last2; + dst->last1inv = src->last1inv; + dst->last2inv = src->last2inv; + dst->sols = src->sols; + dst->sols_mutex = src->sols_mutex; + dst->current_alg = src->current_alg; + dst->sorted_moves = src->sorted_moves; + dst->move_position = src->move_position; + + copy_estimatedata(src->ed, dst->ed); +} + static void -dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd) +dfs(DfsArg *arg) { - if (dfs_stop(c, s, opts, dd)) + bool sw = false; + + if (dfs_stop(arg)) return; - if (dfs_check_solved(s, opts, dd)) + if (dfs_check_solved(arg)) return; - dfs_branch(c, s, opts, dd); + if (arg->step->final && (sw = dfs_switch_final(arg))) + invert_branch(arg); + dfs_branch(arg); + + if (arg->opts->can_niss && !arg->niss && niss_makes_sense(arg)) + dfs_niss(arg); - if (opts->can_niss && !dd->niss) - dfs_niss(c, s, opts, dd); + if (sw) + invert_branch(arg); } static void -dfs_branch(Cube c, Step *s, SolveOptions *opts, DfsData *dd) +dfs_branch(DfsArg *arg) { - bool b = false; int i; - uint64_t mm; - Move m, l1, l2; - LocalInfo li; + Move m; + DfsArg *newarg; - l1 = dd->last1; - l2 = dd->last2; - li = *(dd->ed->li); - mm = dd->ed->movebitmask; + newarg = malloc(sizeof(DfsArg)); + newarg->ed = malloc(sizeof(EstimateData)); - for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { - if (b) - break; - - m = dd->sorted_moves[i]; - if (allowed_next(m, dd, mm)) { - dd->last2 = dd->last1; - dd->last1 = m; - append_move(dd->current_alg, m, dd->niss); - - dfs(apply_move(m, c), s, opts, dd); - - dd->current_alg->len--; - dd->last2 = l2; - dd->last1 = l1; - *(dd->ed->li) = li; + for (i = 0; arg->sorted_moves[i] != NULLMOVE; i++) { + m = arg->sorted_moves[i]; + if (allowed_next(m, arg)) { + copy_dfsarg(arg, newarg); + newarg->last2 = arg->last1; + newarg->last1 = m; + newarg->cube = apply_move(m, arg->cube); + append_move(arg->current_alg, m, newarg->niss); + + dfs(newarg); + + arg->current_alg->len--; } } + + free(newarg->ed); + free(newarg); } static bool -dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd) +dfs_check_solved(DfsArg *arg) { - if (dd->lb != 0) + if (!arg->step->is_done(arg->cube)) return false; - if (dd->current_alg->len == dd->d) { - if (s->is_valid(dd->current_alg) || opts->all) { - pthread_mutex_lock(dd->sols_mutex); - if (dd->sols->len < opts->max_solutions) - append_alg(dd->sols, dd->current_alg); - pthread_mutex_unlock(dd->sols_mutex); + if (arg->current_alg->len == arg->d) { + if ((arg->step->is_valid(arg->current_alg) || arg->opts->all) + && (!arg->step->final || !cancel_niss(arg))) { + pthread_mutex_lock(arg->sols_mutex); + if (arg->sols->len < arg->opts->max_solutions) + append_alg(arg->sols, arg->current_alg); + pthread_mutex_unlock(arg->sols_mutex); } - if (opts->verbose) - print_alg(dd->current_alg, false); + if (arg->opts->verbose) + print_alg(arg->current_alg, false); } return true; } static void -dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd) +dfs_niss(DfsArg *arg) { - Move l1, l2; - EstimateData *ed; - - l1 = dd->last1; - l2 = dd->last2; + DfsArg *newarg; - ed = malloc(sizeof(EstimateData)); - ed->cube = apply_move(inverse_move(l1), (Cube){0}); - ed->target = 1; + newarg = malloc(sizeof(DfsArg)); + newarg->ed = malloc(sizeof(EstimateData)); - if (dd->current_alg->len == 0 || s->estimate(ed)) { - dd->niss = true; - dd->last1 = NULLMOVE; - dd->last2 = NULLMOVE; + copy_dfsarg(arg, newarg); + swapmove(&(newarg->last1), &(newarg->last1inv)); + swapmove(&(newarg->last2), &(newarg->last2inv)); + newarg->niss = !(arg->niss); + newarg->cube = inverse_cube(arg->cube); - dfs(inverse_cube(c), s, opts, dd); - - dd->last1 = l1; - dd->last2 = l2; - dd->niss = false; - } + dfs(newarg); - free(ed); + free(newarg->ed); + free(newarg); } static bool -dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd) +dfs_stop(DfsArg *arg) { + int lowerbound; bool b; - dd->ed->cube = c; - dd->ed->target = dd->d - dd->current_alg->len; - dd->ed->lastmove = dd->last1; - dd->ed->movebitmask = 0; + lowerbound = arg->step->estimate(arg); + if (arg->opts->can_niss && !arg->niss) + lowerbound = MIN(1, lowerbound); - dd->lb = s->estimate(dd->ed); - if (opts->can_niss && !dd->niss) - dd->lb = MIN(1, dd->lb); - - if (dd->current_alg->len + dd->lb > dd->d) { + if (arg->current_alg->len + lowerbound > arg->d) { b = true; } else { - pthread_mutex_lock(dd->sols_mutex); - b = dd->sols->len >= opts->max_solutions; - pthread_mutex_unlock(dd->sols_mutex); + pthread_mutex_lock(arg->sols_mutex); + b = arg->sols->len >= arg->opts->max_solutions; + pthread_mutex_unlock(arg->sols_mutex); } return b; } +static bool +dfs_switch_final(DfsArg *arg) +{ + int i, bn, bi; + + for (bn = 0, i = 0; arg->sorted_moves[i] != NULLMOVE; i++) + if (allowed_next(arg->sorted_moves[i], arg)) + bn++; + + swapmove(&(arg->last1), &(arg->last1inv)); + swapmove(&(arg->last2), &(arg->last2inv)); + swapu64(&(arg->badmoves), &(arg->badmovesinv)); + + for (bi = 0, i = 0; arg->sorted_moves[i] != NULLMOVE; i++) + if (allowed_next(arg->sorted_moves[i], arg)) + bi++; + + swapmove(&(arg->last1), &(arg->last1inv)); + swapmove(&(arg->last2), &(arg->last2inv)); + swapu64(&(arg->badmoves), &(arg->badmovesinv)); + + return bi < bn; +} + static void * instance_thread(void *arg) { @@ -158,7 +211,7 @@ instance_thread(void *arg) Cube c; ThreadDataSolve *td; AlgListNode *node; - DfsData dd; + DfsArg darg; td = (ThreadDataSolve *)arg; @@ -179,34 +232,53 @@ instance_thread(void *arg) apply_move(node->alg->move[0], inverse_cube(td->cube)) : apply_move(node->alg->move[0], td->cube); - dd.d = td->depth; - dd.m = 1; - dd.niss = node->alg->inv[0]; - dd.lb = -1; - dd.last1 = node->alg->move[0]; - dd.last2 = NULLMOVE; - dd.sols = td->sols; - dd.sols_mutex = td->sols_mutex; - dd.current_alg = new_alg(""); - append_move(dd.current_alg, node->alg->move[0], + darg.step = td->step; + darg.opts = td->opts; + darg.cube = c; + darg.d = td->depth; + darg.niss = node->alg->inv[0]; + darg.last1 = node->alg->move[0]; + darg.last2 = NULLMOVE; + darg.last1inv = NULLMOVE; + darg.last2inv = NULLMOVE; + darg.sols = td->sols; + darg.sols_mutex = td->sols_mutex; + darg.current_alg = new_alg(""); + append_move(darg.current_alg, node->alg->move[0], node->alg->inv[0]); - dd.sorted_moves = td->sorted_moves; - dd.move_position = td->move_position; - dd.ed = malloc(sizeof(EstimateData)); - dd.ed->movebitmask = 0; - dd.ed->li = new_localinfo(); + darg.sorted_moves = td->sorted_moves; + darg.move_position = td->move_position; + darg.ed = new_estimatedata(); + darg.badmoves = 0; + darg.badmovesinv = 0; - dfs(c, td->step, td->opts, &dd); + dfs(&darg); - free_alg(dd.current_alg); - free_localinfo(dd.ed->li); - free(dd.ed); + free_alg(darg.current_alg); + free_estimatedata(darg.ed); } return NULL; } static void +invert_branch(DfsArg *arg) +{ + Cube aux; + + aux = arg->cube; + arg->cube = is_solved(arg->inverse) ? + inverse_cube(arg->cube) : arg->inverse; + arg->inverse = aux; + + swapu64(&(arg->badmoves), &(arg->badmovesinv)); + arg->niss = !(arg->niss); + swapmove(&(arg->last1), &(arg->last1inv)); + swapmove(&(arg->last2), &(arg->last2inv)); + invert_estimatedata(arg->ed); +} + +static void multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) { int i, *move_position; @@ -233,6 +305,8 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) for (i = 0; sorted_moves[i] != NULLMOVE; i++) { alg = new_alg(""); + /* TODO: start on inverse also in case of final step + and ed->sw true */ append_move(alg, sorted_moves[i], false); append_alg(start, alg); if (opts->can_niss) { @@ -270,6 +344,15 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) free(sorted_moves); } +static bool +niss_makes_sense(DfsArg *arg) +{ + Cube testcube; + + testcube = apply_move(inverse_move(arg->last1), (Cube){0}); + return arg->current_alg->len == 0 || arg->step->is_done(testcube); +} + /* Public functions **********************************************************/ AlgList * @@ -279,10 +362,8 @@ solve(Cube cube, Step *step, SolveOptions *opts) AlgList *sols; AlgListNode *node; Cube c; - EstimateData *ed; - bool b; - prepare_step(step, opts->nthreads); + prepare_step(step, opts); if (step->detect != NULL) step->pre_trans = step->detect(cube); @@ -296,19 +377,9 @@ solve(Cube cube, Step *step, SolveOptions *opts) return sols; } - if (opts->min_moves == 0) { - ed = malloc(sizeof(EstimateData)); - ed->cube = cube; - ed->target = 0; - ed->li = new_localinfo(); - b = step->estimate(ed) == 0; - free_localinfo(ed->li); - free(ed); - - if (b) { - append_alg(sols, new_alg("")); - return sols; - } + if (opts->min_moves == 0 && step->is_done(cube)) { + append_alg(sols, new_alg("")); + return sols; } for (d = opts->min_moves; @@ -323,8 +394,11 @@ solve(Cube cube, Step *step, SolveOptions *opts) multidfs(c, step, opts, sols, d); } - for (node = sols->first; node != NULL; node = node->next) + for (node = sols->first; node != NULL; node = node->next) { transform_alg(inverse_trans(step->pre_trans), node->alg); + if (step->final) + unniss(node->alg); + } return sols; } diff --git a/src/steps.c b/src/steps.c @@ -5,28 +5,37 @@ /* Checkers, estimators and validators ***************************************/ static bool check_centers(Cube cube); +static bool check_coany_HTM(Cube cube); +static bool check_coud_HTM(Cube cube); +static bool check_coany_URF(Cube cube); +static bool check_coud_URF(Cube cube); +static bool check_corners_HTM(Cube cube); +static bool check_corners_URF(Cube cube); +static bool check_cornershtr(Cube cube); +static bool check_eoany(Cube cube); static bool check_eofb(Cube cube); +static bool check_drany(Cube cube); static bool check_drud(Cube cube); static bool check_htr(Cube cube); -static int estimate_eoany_HTM(EstimateData *ed); -static int estimate_eofb_HTM(EstimateData *ed); -static int estimate_coany_HTM(EstimateData *ed); -static int estimate_coud_HTM(EstimateData *ed); -static int estimate_coany_URF(EstimateData *ed); -static int estimate_coud_URF(EstimateData *ed); -static int estimate_corners_HTM(EstimateData *ed); -static int estimate_cornershtr_HTM(EstimateData *ed); -static int estimate_corners_URF(EstimateData *ed); -static int estimate_cornershtr_URF(EstimateData *ed); -static int estimate_drany_HTM(EstimateData *ed); -static int estimate_drud_HTM(EstimateData *ed); -static int estimate_drud_eofb(EstimateData *ed); -static int estimate_dr_eofb(EstimateData *ed); -static int estimate_drudfin_drud(EstimateData *ed); -static int estimate_htr_drud(EstimateData *ed); -static int estimate_htrfin_htr(EstimateData *ed); -static int estimate_optimal_HTM(EstimateData *ed); +static int estimate_eoany_HTM(DfsArg *arg); +static int estimate_eofb_HTM(DfsArg *arg); +static int estimate_coany_HTM(DfsArg *arg); +static int estimate_coud_HTM(DfsArg *arg); +static int estimate_coany_URF(DfsArg *arg); +static int estimate_coud_URF(DfsArg *arg); +static int estimate_corners_HTM(DfsArg *arg); +static int estimate_cornershtr_HTM(DfsArg *arg); +static int estimate_corners_URF(DfsArg *arg); +static int estimate_cornershtr_URF(DfsArg *arg); +static int estimate_drany_HTM(DfsArg *arg); +static int estimate_drud_HTM(DfsArg *arg); +static int estimate_drud_eofb(DfsArg *arg); +static int estimate_dr_eofb(DfsArg *arg); +static int estimate_drudfin_drud(DfsArg *arg); +static int estimate_htr_drud(DfsArg *arg); +static int estimate_htrfin_htr(DfsArg *arg); +static int estimate_optimal_HTM(DfsArg *arg); static bool always_valid(Alg *alg); static bool validate_singlecw_ending(Alg *alg); @@ -51,6 +60,8 @@ optimal_HTM = { .shortname = "optimal", .name = "Optimal solve (in HTM)", + .final = true, + .is_done = is_solved, .estimate = estimate_optimal_HTM, .ready = check_centers, .ready_msg = check_centers_msg, @@ -69,6 +80,8 @@ eoany_HTM = { .shortname = "eo", .name = "EO on any axis", + .final = false, + .is_done = check_eoany, .estimate = estimate_eoany_HTM, .ready = check_centers, .ready_msg = check_centers_msg, @@ -86,6 +99,8 @@ eofb_HTM = { .shortname = "eofb", .name = "EO on F/B", + .final = false, + .is_done = check_eofb, .estimate = estimate_eofb_HTM, .ready = check_centers, .ready_msg = check_centers_msg, @@ -103,6 +118,8 @@ eorl_HTM = { .shortname = "eorl", .name = "EO on R/L", + .final = false, + .is_done = check_eofb, .estimate = estimate_eofb_HTM, .ready = check_centers, .ready_msg = check_centers_msg, @@ -120,6 +137,8 @@ eoud_HTM = { .shortname = "eoud", .name = "EO on U/D", + .final = false, + .is_done = check_eofb, .estimate = estimate_eofb_HTM, .ready = check_centers, .ready_msg = check_centers_msg, @@ -138,6 +157,8 @@ coany_HTM = { .shortname = "co", .name = "CO on any axis", + .final = false, + .is_done = check_coany_HTM, .estimate = estimate_coany_HTM, .ready = NULL, .is_valid = validate_singlecw_ending, @@ -154,6 +175,8 @@ coud_HTM = { .shortname = "coud", .name = "CO on U/D", + .final = false, + .is_done = check_coud_HTM, .estimate = estimate_coud_HTM, .ready = NULL, .is_valid = validate_singlecw_ending, @@ -170,6 +193,8 @@ corl_HTM = { .shortname = "corl", .name = "CO on R/L", + .final = false, + .is_done = check_coud_HTM, .estimate = estimate_coud_HTM, .ready = NULL, .is_valid = validate_singlecw_ending, @@ -186,6 +211,8 @@ cofb_HTM = { .shortname = "cofb", .name = "CO on F/B", + .final = false, + .is_done = check_coud_HTM, .estimate = estimate_coud_HTM, .ready = NULL, .is_valid = validate_singlecw_ending, @@ -202,6 +229,8 @@ coany_URF = { .shortname = "co-URF", .name = "CO any axis (URF moveset)", + .final = false, + .is_done = check_coany_URF, .estimate = estimate_coany_URF, .ready = NULL, .is_valid = validate_singlecw_ending, @@ -218,6 +247,8 @@ coud_URF = { .shortname = "coud-URF", .name = "CO on U/D (URF moveset)", + .final = false, + .is_done = check_coud_URF, .estimate = estimate_coud_URF, .ready = NULL, .is_valid = validate_singlecw_ending, @@ -234,6 +265,8 @@ corl_URF = { .shortname = "corl-URF", .name = "CO on R/L (URF moveset)", + .final = false, + .is_done = check_coud_URF, .estimate = estimate_coud_URF, .ready = NULL, .is_valid = validate_singlecw_ending, @@ -250,6 +283,8 @@ cofb_URF = { .shortname = "cofb-URF", .name = "CO on F/B (URF moveset)", + .final = false, + .is_done = check_coud_URF, .estimate = estimate_coud_URF, .ready = NULL, .is_valid = validate_singlecw_ending, @@ -267,6 +302,8 @@ cornershtr_HTM = { .shortname = "chtr", .name = "Solve corners to HTR state", + .final = false, + .is_done = check_cornershtr, .estimate = estimate_cornershtr_HTM, .ready = NULL, .is_valid = validate_singlecw_ending, @@ -283,6 +320,8 @@ cornershtr_URF = { .shortname = "chtr-URF", .name = "Solve corners to HTR state (URF moveset)", + .final = false, + .is_done = check_cornershtr, .estimate = estimate_cornershtr_URF, .ready = NULL, .is_valid = validate_singlecw_ending, @@ -299,6 +338,8 @@ corners_HTM = { .shortname = "corners", .name = "Solve corners", + .final = true, + .is_done = check_corners_HTM, .estimate = estimate_corners_HTM, .ready = NULL, .is_valid = always_valid, @@ -315,6 +356,8 @@ corners_URF = { .shortname = "corners-URF", .name = "Solve corners (URF moveset)", + .final = true, /* TODO: check if this works with reorient */ + .is_done = check_corners_URF, .estimate = estimate_corners_URF, .ready = NULL, .is_valid = always_valid, @@ -332,6 +375,8 @@ drany_HTM = { .shortname = "dr", .name = "DR on any axis", + .final = false, + .is_done = check_drany, .estimate = estimate_drany_HTM, .ready = check_centers, .ready_msg = check_centers_msg, @@ -349,6 +394,8 @@ drud_HTM = { .shortname = "drud", .name = "DR on U/D", + .final = false, + .is_done = check_drud, .estimate = estimate_drud_HTM, .ready = check_centers, .ready_msg = check_centers_msg, @@ -366,6 +413,8 @@ drrl_HTM = { .shortname = "drrl", .name = "DR on R/L", + .final = false, + .is_done = check_drud, .estimate = estimate_drud_HTM, .ready = check_centers, .ready_msg = check_centers_msg, @@ -383,6 +432,8 @@ drfb_HTM = { .shortname = "drfb", .name = "DR on F/B", + .final = false, + .is_done = check_drud, .estimate = estimate_drud_HTM, .ready = check_centers, .ready_msg = check_centers_msg, @@ -401,6 +452,8 @@ dr_eo = { .shortname = "dr-eo", .name = "DR without breaking EO (automatically detected)", + .final = false, + .is_done = check_drud, .estimate = estimate_dr_eofb, .ready = check_eofb, .ready_msg = check_eo_msg, @@ -418,6 +471,8 @@ dr_eofb = { .shortname = "dr-eofb", .name = "DR on U/D or R/L without breaking EO on F/B", + .final = false, + .is_done = check_drud, .estimate = estimate_dr_eofb, .ready = check_eofb, .ready_msg = check_eo_msg, @@ -435,6 +490,8 @@ dr_eorl = { .shortname = "dr-eorl", .name = "DR on U/D or F/B without breaking EO on R/L", + .final = false, + .is_done = check_drud, .estimate = estimate_dr_eofb, .ready = check_eofb, .ready_msg = check_eo_msg, @@ -452,6 +509,8 @@ dr_eoud = { .shortname = "dr-eoud", .name = "DR on R/L or F/B without breaking EO on U/D", + .final = false, + .is_done = check_drud, .estimate = estimate_dr_eofb, .ready = check_eofb, .ready_msg = check_eo_msg, @@ -469,6 +528,8 @@ drud_eofb = { .shortname = "drud-eofb", .name = "DR on U/D without breaking EO on F/B", + .final = false, + .is_done = check_drud, .estimate = estimate_drud_eofb, .ready = check_eofb, .ready_msg = check_eo_msg, @@ -486,6 +547,8 @@ drrl_eofb = { .shortname = "drrl-eofb", .name = "DR on R/L without breaking EO on F/B", + .final = false, + .is_done = check_drud, .estimate = estimate_drud_eofb, .ready = check_eofb, .ready_msg = check_eo_msg, @@ -503,6 +566,8 @@ drud_eorl = { .shortname = "drud-eorl", .name = "DR on U/D without breaking EO on R/L", + .final = false, + .is_done = check_drud, .estimate = estimate_drud_eofb, .ready = check_eofb, .ready_msg = check_eo_msg, @@ -520,6 +585,8 @@ drfb_eorl = { .shortname = "drfb-eorl", .name = "DR on F/B without breaking EO on R/L", + .final = false, + .is_done = check_drud, .estimate = estimate_drud_eofb, .ready = check_eofb, .ready_msg = check_eo_msg, @@ -537,6 +604,8 @@ drfb_eoud = { .shortname = "drfb-eoud", .name = "DR on F/B without breaking EO on U/D", + .final = false, + .is_done = check_drud, .estimate = estimate_drud_eofb, .ready = check_eofb, .ready_msg = check_eo_msg, @@ -554,6 +623,8 @@ drrl_eoud = { .shortname = "drrl-eoud", .name = "DR on R/L without breaking EO on U/D", + .final = false, + .is_done = check_drud, .estimate = estimate_drud_eofb, .ready = check_eofb, .ready_msg = check_eo_msg, @@ -572,6 +643,8 @@ dranyfin_DR = { .shortname = "drfin", .name = "DR finish on any axis without breaking DR", + .final = true, + .is_done = is_solved, .estimate = estimate_drudfin_drud, .ready = check_drud, .ready_msg = check_drany_msg, @@ -589,6 +662,8 @@ drudfin_drud = { .shortname = "drudfin", .name = "DR finish on U/D without breaking DR", + .final = true, + .is_done = is_solved, .estimate = estimate_drudfin_drud, .ready = check_drud, .ready_msg = check_dr_msg, @@ -606,6 +681,8 @@ drrlfin_drrl = { .shortname = "drrlfin", .name = "DR finish on R/L without breaking DR", + .final = true, + .is_done = is_solved, .estimate = estimate_drudfin_drud, .ready = check_drud, .ready_msg = check_dr_msg, @@ -623,6 +700,8 @@ drfbfin_drfb = { .shortname = "drfbfin", .name = "DR finish on F/B without breaking DR", + .final = true, + .is_done = is_solved, .estimate = estimate_drudfin_drud, .ready = check_drud, .ready_msg = check_dr_msg, @@ -641,6 +720,8 @@ htr_any = { .shortname = "htr", .name = "HTR from DR", + .final = false, + .is_done = check_htr, .estimate = estimate_htr_drud, .ready = check_drud, .ready_msg = check_drany_msg, @@ -658,6 +739,8 @@ htr_drud = { .shortname = "htr-drud", .name = "HTR from DR on U/D", + .final = false, + .is_done = check_htr, .estimate = estimate_htr_drud, .ready = check_drud, .ready_msg = check_dr_msg, @@ -675,6 +758,8 @@ htr_drrl = { .shortname = "htr-drrl", .name = "HTR from DR on R/L", + .final = false, + .is_done = check_htr, .estimate = estimate_htr_drud, .ready = check_drud, .ready_msg = check_dr_msg, @@ -692,6 +777,8 @@ htr_drfb = { .shortname = "htr-drfb", .name = "HTR from DR on F/B", + .final = false, + .is_done = check_htr, .estimate = estimate_htr_drud, .ready = check_drud, .ready_msg = check_dr_msg, @@ -710,6 +797,8 @@ htrfin_htr = { .shortname = "htrfin", .name = "HTR finish without breaking HTR", + .final = true, + .is_done = is_solved, .estimate = estimate_htrfin_htr, .ready = check_htr, .ready_msg = check_htr_msg, @@ -783,12 +872,89 @@ check_centers(Cube cube) } static bool +check_coany_HTM(Cube cube) +{ + return cube.cofb == 0 || cube.corl == 0 || cube.coud == 0; +} + +static bool +check_coud_HTM(Cube cube) +{ + return cube.coud == 0; +} + +static bool +check_coany_URF(Cube cube) +{ + Cube c2, c3; + + c2 = apply_move(y, apply_move(z, cube)); + c3 = apply_move(y, apply_move(x, cube)); + + return check_coany_HTM(cube) || + check_coany_HTM(c2) || + check_coany_HTM(c3); +} + +static bool +check_coud_URF(Cube cube) +{ + Cube c2, c3; + + c2 = apply_move(z, cube); + c3 = apply_move(x, cube); + + return cube.coud == 0 || c2.coud == 0 || c3.coud == 0; +} + +static bool +check_corners_URF(Cube cube) +{ + Cube c; + Trans i; + + for (i = 0; i < NROTATIONS; i++) { + c = apply_alg(rotation_alg(i), cube); + if (c.cp && c.coud) + return true; + } + + return false; +} + +static bool +check_corners_HTM(Cube cube) +{ + return cube.cp == 0 && cube.coud == 0; +} + +static bool +check_cornershtr(Cube cube) +{ + return coord_cornershtr.index(cube) == 0; +} + +static bool +check_eoany(Cube cube) +{ + return cube.eofb == 0 || cube.eorl == 0 || cube.eoud == 0; +} + +static bool check_eofb(Cube cube) { return cube.eofb == 0; } static bool +check_drany(Cube cube) +{ + return (cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0) || + (cube.eorl == 0 && cube.eoud == 0 && cube.cofb == 0) || + (cube.eoud == 0 && cube.eofb == 0 && cube.corl == 0); +} + +static bool check_drud(Cube cube) { return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; @@ -801,265 +967,283 @@ check_htr(Cube cube) } static int -estimate_eoany_HTM(EstimateData *ed) +estimate_eoany_HTM(DfsArg *arg) { int r1, r2, r3; - r1 = ptableval(&pd_eofb_HTM, ed->cube); - r2 = ptableval(&pd_eofb_HTM, apply_trans(ur, ed->cube)); - r3 = ptableval(&pd_eofb_HTM, apply_trans(fd, ed->cube)); + r1 = ptableval(&pd_eofb_HTM, arg->cube); + r2 = ptableval(&pd_eofb_HTM, apply_trans(ur, arg->cube)); + r3 = ptableval(&pd_eofb_HTM, apply_trans(fd, arg->cube)); return MIN(r1, MIN(r2, r3)); } static int -estimate_eofb_HTM(EstimateData *ed) +estimate_eofb_HTM(DfsArg *arg) { - return ptableval(&pd_eofb_HTM, ed->cube); + return ptableval(&pd_eofb_HTM, arg->cube); } static int -estimate_coany_HTM(EstimateData *ed) +estimate_coany_HTM(DfsArg *arg) { int r1, r2, r3; - r1 = ptableval(&pd_coud_HTM, ed->cube); - r2 = ptableval(&pd_coud_HTM, apply_trans(rf, ed->cube)); - r3 = ptableval(&pd_coud_HTM, apply_trans(fd, ed->cube)); + r1 = ptableval(&pd_coud_HTM, arg->cube); + r2 = ptableval(&pd_coud_HTM, apply_trans(rf, arg->cube)); + r3 = ptableval(&pd_coud_HTM, apply_trans(fd, arg->cube)); return MIN(r1, MIN(r2, r3)); } static int -estimate_coud_HTM(EstimateData *ed) +estimate_coud_HTM(DfsArg *arg) { - return ptableval(&pd_coud_HTM, ed->cube); + return ptableval(&pd_coud_HTM, arg->cube); } static int -estimate_coany_URF(EstimateData *ed) +estimate_coany_URF(DfsArg *arg) { int r1, r2, r3; - EstimateData *ed2, *ed3; - - ed2 = malloc(sizeof(EstimateData)); - ed3 = malloc(sizeof(EstimateData)); - - ed2->cube = apply_trans(rf, ed->cube); - ed2->target = ed->target; + Cube c; - ed3->cube = apply_trans(fd, ed->cube); - ed3->target = ed->target; + c = arg->cube; - r1 = estimate_coud_URF(ed); - r2 = estimate_coud_URF(ed2); - r3 = estimate_coud_URF(ed3); + r1 = estimate_coud_URF(arg); + arg->cube = apply_trans(rf, c); + r2 = estimate_coud_URF(arg); + arg->cube = apply_trans(fd, c); + r3 = estimate_coud_URF(arg); - free(ed2); - free(ed3); + arg->cube = c; return MIN(r1, MIN(r2, r3)); } static int -estimate_coud_URF(EstimateData *ed) +estimate_coud_URF(DfsArg *arg) { /* TODO: I can improve this by checking first the orientation of * the corner in DBL and use that as a reference */ - EstimateData *ed2, *ed3; + Cube c; - ed2 = malloc(sizeof(EstimateData)); - ed2->cube = apply_move(z, ed->cube); - ed2->target = ed->target; + c = arg->cube; - ed3 = malloc(sizeof(EstimateData)); - ed3->cube = apply_move(x, ed->cube); - ed3->target = ed->target; + int ud = estimate_coud_HTM(arg); + arg->cube = apply_move(z, c); + int rl = estimate_coud_HTM(arg); + arg->cube = apply_move(x, c); + int fb = estimate_coud_HTM(arg); - int ud = estimate_coud_HTM(ed); - int rl = estimate_coud_HTM(ed2); - int fb = estimate_coud_HTM(ed3); - - free(ed2); - free(ed3); + arg->cube = c; return MIN(ud, MIN(rl, fb)); } static int -estimate_corners_HTM(EstimateData *ed) +estimate_corners_HTM(DfsArg *arg) { - return ptableval(&pd_corners_HTM, ed->cube); + return ptableval(&pd_corners_HTM, arg->cube); } static int -estimate_cornershtr_HTM(EstimateData *ed) +estimate_cornershtr_HTM(DfsArg *arg) { - return ptableval(&pd_cornershtr_HTM, ed->cube); + return ptableval(&pd_cornershtr_HTM, arg->cube); } static int -estimate_cornershtr_URF(EstimateData *ed) +estimate_cornershtr_URF(DfsArg *arg) { /* TODO: I can improve this by checking first the corner in DBL * and use that as a reference */ - int c, ret = 15; + int ret; + Cube c; Trans i; + c = arg->cube; + ret = 15; + for (i = 0; i < NROTATIONS; i++) { - ed->cube = apply_alg(rotation_alg(i), ed->cube); - c = estimate_cornershtr_HTM(ed); - ret = MIN(ret, c); + arg->cube = apply_alg(rotation_alg(i), c); + ret = MIN(ret, estimate_cornershtr_HTM(arg)); } + arg->cube = c; + return ret; } static int -estimate_corners_URF(EstimateData *ed) +estimate_corners_URF(DfsArg *arg) { /* TODO: I can improve this by checking first the corner in DBL * and use that as a reference */ - int c, ret = 15; + int ret; + Cube c; Trans i; + c = arg->cube; + ret = 15; + for (i = 0; i < NROTATIONS; i++) { - ed->cube = apply_alg(rotation_alg(i), ed->cube); - c = estimate_corners_HTM(ed); - ret = MIN(ret, c); + arg->cube = apply_alg(rotation_alg(i), c); + ret = MIN(ret, estimate_corners_HTM(arg)); } + arg->cube = c; + return ret; } static int -estimate_drany_HTM(EstimateData *ed) +estimate_drany_HTM(DfsArg *arg) { int r1, r2, r3; - r1 = ptableval(&pd_drud_sym16_HTM, ed->cube); - r2 = ptableval(&pd_drud_sym16_HTM, apply_trans(rf, ed->cube)); - r3 = ptableval(&pd_drud_sym16_HTM, apply_trans(fd, ed->cube)); + r1 = ptableval(&pd_drud_sym16_HTM, arg->cube); + r2 = ptableval(&pd_drud_sym16_HTM, apply_trans(rf, arg->cube)); + r3 = ptableval(&pd_drud_sym16_HTM, apply_trans(fd, arg->cube)); return MIN(r1, MIN(r2, r3)); } static int -estimate_drud_HTM(EstimateData *ed) +estimate_drud_HTM(DfsArg *arg) { - return ptableval(&pd_drud_sym16_HTM, ed->cube); + return ptableval(&pd_drud_sym16_HTM, arg->cube); } static int -estimate_drud_eofb(EstimateData *ed) +estimate_drud_eofb(DfsArg *arg) { - return ptableval(&pd_drud_eofb, ed->cube); + return ptableval(&pd_drud_eofb, arg->cube); } static int -estimate_dr_eofb(EstimateData *ed) +estimate_dr_eofb(DfsArg *arg) { int r1, r2; - r1 = ptableval(&pd_drud_eofb, ed->cube); - r2 = ptableval(&pd_drud_eofb, apply_trans(rf, ed->cube)); + r1 = ptableval(&pd_drud_eofb, arg->cube); + r2 = ptableval(&pd_drud_eofb, apply_trans(rf, arg->cube)); return MIN(r1, r2); } static int -estimate_drudfin_drud(EstimateData *ed) +estimate_drudfin_drud(DfsArg *arg) { - int val = ptableval(&pd_drudfin_noE_sym16_drud, ed->cube); + int val = ptableval(&pd_drudfin_noE_sym16_drud, arg->cube); if (val != 0) return val; - return ed->cube.epose % 24 == 0 ? 0 : 1; + return arg->cube.epose % 24 == 0 ? 0 : 1; } static int -estimate_htr_drud(EstimateData *ed) +estimate_htr_drud(DfsArg *arg) { - return ptableval(&pd_htr_drud, ed->cube); + return ptableval(&pd_htr_drud, arg->cube); } static int -estimate_htrfin_htr(EstimateData *ed) +estimate_htrfin_htr(DfsArg *arg) { - return ptableval(&pd_htrfin_htr, ed->cube); + return ptableval(&pd_htrfin_htr, arg->cube); } static int -estimate_optimal_HTM(EstimateData *ed) +estimate_optimal_HTM(DfsArg *arg) { - int ret = -1; + int target, ret; Move lbase; - Cube cubeaux, inv; - - ed->li->corners = ptableval(&pd_corners_HTM, ed->cube); - UPDATECHECKSTOP(ret, ed->li->corners, ed->target); - - ed->li->normal_ud = ptableval(&pd_khuge_HTM, ed->cube); - UPDATECHECKSTOP(ret, ed->li->normal_ud, ed->target); + Cube aux; + + target = arg->d - arg->current_alg->len; + ret = -1; + arg->inverse = (Cube){0}; + arg->badmovesinv = 0; + arg->badmoves = 0; + + arg->ed->corners = ptableval(&pd_corners_HTM, arg->cube); + UPDATECHECKSTOP(ret, arg->ed->corners, target); + + arg->ed->normal_ud = ptableval(&pd_khuge_HTM, arg->cube); + UPDATECHECKSTOP(ret, arg->ed->normal_ud, target); + if (arg->ed->normal_ud == target) { + arg->badmovesinv |= (1<<U) | (1<<U2) | (1<<U3) | + (1<<D) | (1<<D2) | (1<<D3); + } - cubeaux = apply_trans(fd, ed->cube); - ed->li->normal_fb = ptableval(&pd_khuge_HTM, cubeaux); - UPDATECHECKSTOP(ret, ed->li->normal_fb, ed->target); + aux = apply_trans(fd, arg->cube); + arg->ed->normal_fb = ptableval(&pd_khuge_HTM, aux); + UPDATECHECKSTOP(ret, arg->ed->normal_fb, target); + if (arg->ed->normal_fb == target) { + arg->badmovesinv |= (1<<F) | (1<<F2) | (1<<F3) | + (1<<B) | (1<<B2) | (1<<B3); + } - cubeaux = apply_trans(rf, ed->cube); - ed->li->normal_rl = ptableval(&pd_khuge_HTM, cubeaux); - UPDATECHECKSTOP(ret, ed->li->normal_rl, ed->target); + aux = apply_trans(rf, arg->cube); + arg->ed->normal_rl = ptableval(&pd_khuge_HTM, aux); + UPDATECHECKSTOP(ret, arg->ed->normal_rl, target); + if (arg->ed->normal_rl == target) { + arg->badmovesinv |= (1<<R) | (1<<R2) | (1<<R3) | + (1<<L) | (1<<L2) | (1<<L3); + } if (ret == 0) return ret; - if (ed->li->normal_ud == ed->li->normal_fb && - ed->li->normal_fb == ed->li->normal_rl) - UPDATECHECKSTOP(ret, ed->li->normal_ud + 1, ed->target); + if (arg->ed->normal_ud == arg->ed->normal_fb && + arg->ed->normal_fb == arg->ed->normal_rl) + UPDATECHECKSTOP(ret, arg->ed->normal_ud + 1, target); /* TODO: avoid computation of inverse if unnecessary */ - lbase = base_move(ed->lastmove); - inv = inverse_cube(ed->cube); + lbase = base_move(arg->last1); + arg->inverse = inverse_cube(arg->cube); - if ((lbase != U && lbase != D) || - (ed->li->inverse_ud == -1)) { - ed->li->inverse_ud = ptableval(&pd_khuge_HTM, inv); + if ((lbase != U && lbase != D) || (arg->ed->inverse_ud == -1)) { + arg->ed->inverse_ud = ptableval(&pd_khuge_HTM, arg->inverse); } - UPDATECHECKSTOP(ret, ed->li->inverse_ud, ed->target); + UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); - if ((lbase != F && lbase != B) || - (ed->li->inverse_fb == -1)) { - cubeaux = apply_trans(fd, inv); - ed->li->inverse_fb = ptableval(&pd_khuge_HTM, cubeaux); + if ((lbase != F && lbase != B) || (arg->ed->inverse_fb == -1)) { + aux = apply_trans(fd, arg->inverse); + arg->ed->inverse_fb = ptableval(&pd_khuge_HTM, aux); } - UPDATECHECKSTOP(ret, ed->li->inverse_fb, ed->target); + UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); - if ((lbase != R && lbase != L) || - (ed->li->inverse_rl == -1)) { - cubeaux = apply_trans(rf, inv); - ed->li->inverse_rl = ptableval(&pd_khuge_HTM, cubeaux); + if ((lbase != R && lbase != L) || (arg->ed->inverse_rl == -1)) { + aux = apply_trans(rf, arg->inverse); + arg->ed->inverse_rl = ptableval(&pd_khuge_HTM, aux); } - UPDATECHECKSTOP(ret, ed->li->inverse_rl, ed->target); - - if (ed->li->inverse_ud == ed->li->inverse_fb && - ed->li->inverse_fb == ed->li->inverse_rl) - UPDATECHECKSTOP(ret, ed->li->inverse_ud + 1, ed->target); - - if (ed->li->inverse_ud == ed->target) - ed->movebitmask |= (1<<U) | (1<<U2) | (1<<U3) | - (1<<D) | (1<<D2) | (1<<D3); - if (ed->li->inverse_fb == ed->target) - ed->movebitmask |= (1<<F) | (1<<F2) | (1<<F3) | - (1<<B) | (1<<B2) | (1<<B3); - if (ed->li->inverse_rl == ed->target) - ed->movebitmask |= (1<<R) | (1<<R2) | (1<<R3) | - (1<<L) | (1<<L2) | (1<<L3); + UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); - return ret; + if (arg->ed->inverse_ud == arg->ed->inverse_fb && + arg->ed->inverse_fb == arg->ed->inverse_rl) { + UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target); + } + + if (arg->ed->inverse_ud == target) { + arg->badmoves |= (1<<U) | (1<<U2) | (1<<U3) | + (1<<D) | (1<<D2) | (1<<D3); + } + if (arg->ed->inverse_fb == target) { + arg->badmoves |= (1<<F) | (1<<F2) | (1<<F3) | + (1<<B) | (1<<B2) | (1<<B3); + } + if (arg->ed->inverse_rl == target) { + arg->badmoves |= (1<<R) | (1<<R2) | (1<<R3) | + (1<<L) | (1<<L2) | (1<<L3); + } + + return arg->ed->oldret = ret; } static bool @@ -1120,15 +1304,36 @@ detect_pretrans_drud(Cube cube) /* Public functions **********************************************************/ void -free_localinfo(LocalInfo *li) +copy_estimatedata(EstimateData *src, EstimateData *dst) +{ + dst->corners = src->corners; + dst->normal_ud = src->normal_ud; + dst->normal_fb = src->normal_fb; + dst->normal_rl = src->normal_rl; + dst->inverse_ud = src->inverse_ud; + dst->inverse_fb = src->inverse_fb; + dst->inverse_rl = src->inverse_rl; + dst->oldret = src->oldret; +} + +void +free_estimatedata(EstimateData *ed) { - free(li); + free(ed); } -LocalInfo * -new_localinfo() +void +invert_estimatedata(EstimateData *ed) { - LocalInfo *ret = malloc(sizeof(LocalInfo)); + swap(&(ed->normal_ud), &(ed->inverse_ud)); + swap(&(ed->normal_fb), &(ed->inverse_fb)); + swap(&(ed->normal_rl), &(ed->inverse_rl)); +} + +EstimateData * +new_estimatedata() +{ + EstimateData *ret = malloc(sizeof(EstimateData)); ret->corners = -1; ret->normal_ud = -1; @@ -1137,16 +1342,22 @@ new_localinfo() ret->inverse_ud = -1; ret->inverse_fb = -1; ret->inverse_rl = -1; - ret->prev_ret = -1; + ret->oldret = -1; return ret; } void -prepare_step(Step *step, int nthreads) +prepare_step(Step *step, SolveOptions *opts) { int i; + if (step->final && opts->can_niss) { + opts->can_niss = false; + fprintf(stderr, "Step if final, niss not used" + "(-n ignored)\n"); + } + for (i = 0; i < step->ntables; i++) - genptable(step->tables[i], nthreads); + genptable(step->tables[i], opts->nthreads); } diff --git a/src/steps.h b/src/steps.h @@ -7,8 +7,10 @@ extern Step * steps[NSTEPS]; -void free_localinfo(LocalInfo *li); -LocalInfo * new_localinfo(); -void prepare_step(Step *step, int nthreads); +void copy_estimatedata(EstimateData *s, EstimateData *d); +void free_estimatedata(EstimateData *ed); +void invert_estimatedata(EstimateData *ed); +EstimateData * new_estimatedata(); +void prepare_step(Step *step, SolveOptions *opts); #endif diff --git a/src/utils.c b/src/utils.c @@ -272,7 +272,17 @@ swap(int *a, int *b) int aux; aux = *a; - *a = *b; - *b = aux; + *a = *b; + *b = aux; +} + +void +swapu64(uint64_t *a, uint64_t *b) +{ + uint64_t aux; + + aux = *a; + *a = *b; + *b = aux; } diff --git a/src/utils.h b/src/utils.h @@ -2,6 +2,7 @@ #define UTILS_H #include <stdbool.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> @@ -37,5 +38,6 @@ int powint(int a, int b); int subset_to_index(int *a, int n, int k); void sum_arrays_mod(int *src, int *dst, int n, int m); void swap(int *a, int *b); +void swapu64(uint64_t *a, uint64_t *b); #endif