commit 8fb4670e3d76387b8afb3c8ac81ed09741bf6a15
parent 7c7cf8a8689dcbbbca5e3604a464d2526db31a2b
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date: Fri, 14 Apr 2023 18:54:58 +0200
Removed some files from old version
Diffstat:
D | INSTALL | | | 81 | ------------------------------------------------------------------------------- |
M | Makefile | | | 47 | ++--------------------------------------------- |
M | README.md | | | 98 | +------------------------------------------------------------------------------ |
D | TODO.md | | | 142 | ------------------------------------------------------------------------------- |
D | main.c | | | 0 | |
D | old/maybe-useful-coord.c | | | 181 | ------------------------------------------------------------------------------- |
D | old/maybe-useful-steps.c | | | 1111 | ------------------------------------------------------------------------------- |
D | www/download/index.html | | | 212 | ------------------------------------------------------------------------------- |
D | www/examples/index.html | | | 49 | ------------------------------------------------- |
D | www/favicon.png | | | 0 | |
D | www/index.html | | | 93 | ------------------------------------------------------------------------------- |
D | www/screenshot.png | | | 0 | |
D | www/style-2.css | | | 105 | ------------------------------------------------------------------------------- |
13 files changed, 3 insertions(+), 2116 deletions(-)
diff --git a/INSTALL b/INSTALL
@@ -1,81 +0,0 @@
-# Website
-
-Nissy is available at https://nissy.tronto.net
-
-# Requirements
-
-A full installation of nissy requires about 3Gb of space, of which
-2.3Gb are occupied by the huge pruning table for fast optimal solving,
-and running it requires the same amount of RAM. One can choose to never
-use this function and not to install the relative pruning table. There
-is an alternative (slower) optimal solving function that uses about
-500Mb of RAM. When generating the pruning tables automatically (see
-the section Tables below), at least 5.3Gb or RAM are required.
-
-# Installation
-
-## On Windows
-
-Try downloading and executing in a terminal the file nissy.exe, then
-follow the instructions in the Tables section below for installing the
-pruning tables. If nissy.exe does not work, you can try following the
-UNIX instructions in WSL (Windows Subsystem for Linux) or in a similar
-environment.
-
-## On a UNIX system:
-
-Download the source archive (.tar.gz). Extract it with your favorite
-archive program, for example with
-
- tar -xvzf nissy-VERSION.tar.gz
-
-Open a terminal in the directory just extracted. If you wish, edit the
-Makefile to match your local configuration (this is usually not necessary,
-but you may want to change the PREFIX variable to change the installation
-path) and run
-
- make
-
-followed by
-
- make install
-
-Then follow the instructions below to install the pruning tables.
-
-## Tables
-
-Once you have installed nissy, run
-
- nissy gen
-
-to generate all the tables that Nissy will ever need. Running this
-command requires around 5.3Gb of RAM, and it can take some time (about
-40 minutes on my fairly old but decent laptop, with 8 CPU threads).
-
-Some unnecessary technical detail: by default this command is going to
-use at most 64 threads. If you want you can choose to use more threads
-(if your CPU is very powerful) or fewer threads (if you for example
-want to run this command in the background while you do other stuff)
-with the -t option, for example nissy gen -t 1.
-
-Alternatively, you can download all the tables (1.7Gb) and copy them
-into the correct folder (see manual page, ENVIRONMENT section). On UNIX
-operating systems this folder is either .nissy/tables in the user's
-home directory or $XDG_DATA_HOME/nissy/tables if the XDG variable
-is configured. On Windows it is the same directory as the nissy.exe
-executable file.
-
-You can downloads all the tables from the following link:
-
- https://nissy.tronto.net/nissy-tables-2.0.2.zip
-
-# Upgrading
-
-If you already have nissy installed and you want to upgrade to a more
-recent version, you can simply repeat the installation process:
-* On Windows: simply replace nissy.exe with the new file with the same name.
-* On UNIX systems: download the new version of the source code, extract it
- in a new folder and run make and make install again.
-
-Between each version new table files might have been added, or old ones
-may be not used anymore. Nissy will deal with this automatically.
diff --git a/Makefile b/Makefile
@@ -1,9 +1,8 @@
# See LICENSE file for copyright and license details.
-VERSION = post-2.0.2
+VERSION = pre-3.0
PREFIX = /usr/local
-MANPREFIX = ${PREFIX}/share/man
CPPFLAGS = -DVERSION=\"${VERSION}\"
CFLAGS = -std=c99 -pthread -pedantic -Wall -Wextra \
@@ -14,55 +13,13 @@ DBGFLAGS = -std=c99 -pthread -pedantic -Wall -Wextra \
CC = cc
-
all: nissy
nissy: clean
${CC} ${CFLAGS} -o nissy src/*.c
-nissy.exe:
- x86_64-w64-mingw32-gcc ${CFLAGS} -static -o nissy.exe src/*.c
-
debug:
${CC} ${DBGFLAGS} -o nissy src/*.c
-clean:
- rm -rf nissy nissy*.exe nissy*.tar.gz doc/nissy.html doc/nissy.pdf
-
-dist: clean nissy.exe
- mkdir -p nissy-${VERSION}
- cp -R LICENSE Makefile INSTALL doc src nissy-${VERSION}
- groff -Tpdf -mandoc doc/nissy.1 > doc/nissy.pdf
- groff -Thtml -mandoc doc/nissy.1 > doc/nissy.html
- cp doc/nissy.pdf nissy-${VERSION}/doc/nissy.pdf
- cp doc/nissy.html nissy-${VERSION}/doc/nissy.html
- tar -cf nissy-${VERSION}.tar nissy-${VERSION}
- gzip nissy-${VERSION}.tar
- rm -rf nissy-${VERSION}
- mv nissy.exe nissy-${VERSION}.exe
-
-upload: dist
- rsync -v --rsync-path=openrsync nissy-${VERSION}.exe \
- tronto.net:/var/www/htdocs/nissy.tronto.net/
- rsync -v --rsync-path=openrsync nissy-${VERSION}.tar.gz \
- tronto.net:/var/www/htdocs/nissy.tronto.net/
-
-website:
- rsync -rv --rsync-path=openrsync \
- www/ tronto.net:/var/www/htdocs/nissy.tronto.net
-
-install: nissy
- mkdir -p ${DESTDIR}${PREFIX}/bin
- cp -f nissy ${DESTDIR}${PREFIX}/bin/nissy
- chmod 755 ${DESTDIR}${PREFIX}/bin/nissy
- mkdir -p ${DESTDIR}${MANPREFIX}/man1
- sed "s/VERSION/${VERSION}/g" < doc/nissy.1 \
- > ${DESTDIR}${MANPREFIX}/man1/nissy.1
- chmod 644 ${DESTDIR}${MANPREFIX}/man1/nissy.1
-
-uninstall:
- rm -rf ${DESTDIR}${PREFIX}/bin/nissy ${DESTDIR}${MANPREFIX}/man1/nissy.1
- for s in ${SCRIPTS}; do rm -rf ${DESTDIR}${PREFIX}/bin/$$s; done
-
-.PHONY: all debug clean dist install uninstall upload
+.PHONY: all debug
diff --git a/README.md b/README.md
@@ -1,97 +1 @@
-# Nissy
-
-A Rubik's cube solver and FMC assistant.
-For optimal HTM solving Nissy uses techniques from Herbert Kociemba's
-[Cube Explorer](http://kociemba.org/cube.htm) and Tomas Rokicki's
-[nxopt](https://github.com/rokicki/cube20src/blob/master/nxopt.md).
-With 4 cores at 2.5GHz and using about 3Gb of RAM, Nissy can find an
-optimal solution in about a minute on average.
-
-Nissy can also solve many different substeps of Thistlethwaite's algorithm
-(DR/HTR), and can use NISS (Normal-Inverse Scramble Switch).
-It can be useful to analyze your DR solves (and more, once I implement more features).
-
-You can get Nissy from [nissy.tronto.net](https://nissy.tronto.net).
-The download links and installation instructions can be found on the
-[download page](https://nissy.tronto.net/download).
-
-## Structure of the code
-
-You can find all the source code in the `src` folder.
-I strived to keep it legible but I did not write many comments (barely any at all).
-I'll try to explain here the main parts of the program.
-
-### Cube, moves and transformations
-
-There are many ways to represent a cube. In Nissy I use two:
-
-* An array representation `CubeArray`: 3 arrays representing the permutation
-of corners, edges and centers and 2 arrays for the orientation of corners and edges.
-* An 11-integers representation `Cube`: 3 integers for edge orientation (with respect
-to the three axes), 3 for corner orientation, and so on. Edge permutation is a bit
-complicated because encoding 12 factorial as a single number is too large for some
-practical reasons, so I use 3 integers for that.
-
-Moves are easy to apply on the array form, but they are slow. So `moves.c`
-contains the instructions to create all the transition tables necessary
-to get the next position for the cube with just 11 lookup operations
-(one for each of the 11 integers in the second representation).
-These transition tables are saved in the `mtables` file in the
-`tables` folder in binary format.
-
-The 11 integers are obviously redundant, but keeping all of them makes it easy
-to apply transformations. A transformation is a rotation of the whole cube, possibly
-combined with a mirror operation. Applying a transformation to a cube (say obtained
-by applying a scramble to the solved cube) means applying the transformation to a
-solved cube, then the scramble and then the inverse of the transformation
-(i.e. conjugating by it).
-
-### Coordinates and pruning tables
-
-A *coordinate* consists of a function that takes a cube (in the 11-integer
-representation) and return an (unsigned, 64-bit) integer. They are used
-to "linearize" a cube and build pruning tables, which speed up significantly the
-solving process. To be able to access the pruning table quickly, the function
-needs to be very fast (e.g. it should not convert between the two representations
-of the cube if not necessary).
-
-Some coordinates make use of symmetries to reduce the size of the resulting
-pruning table. Unfortunately this complicates the code a lot, but it is a huge
-advantage: it reduces by a factor of about 16 the pruning table size.
-
-Pruning tables are related to a specific step, a moveset and a coordinate. They
-contain one value from 0 to 15 (4 bits) for each possible value for the coordinate,
-which is less or equal than the minimum number of moves required to solve the
-given step with the given moveset for a cube which has the given coordinate. For example,
-say the coordinate `neo` gives the number of non-oriented edges (say with respect to
-F/B). Then the possible values for the coordinate are 0,2,4,...,12. An associated
-pruning table to solving EO with HTM moveset and this coordinate would have values 0
-(for `neo=0`), 3 (for `neo=2`), 1 (for `neo=4`)...
-
-The values for most pruning tables are memorized modulo 16, so they only occupy
-4 bits per entry, and values larger than 15 are saved as 15. This is good enough
-for most applications.
-Some large tables are memorized in compact form using only 2 bits, similarly
-to what [nxopt](https://github.com/rokicki/cube20src/blob/master/nxopt.md) does:
-a base value `b` is picked and a value of `n` is saved as `MIN(3,MAX(0,n-b))`.
-When a value of `v=1,2,3` is read it is simply returned as `v+b`, while if
-`0` is a successive lookup to a fallback table is performed. The base value `b`
-is picked to maximize the sum frequency of the values `1,2,3`.
-
-In order to generate the pruning tables, it is necessary to be able to move
-a transform a coordinate; it is possible to do so without passing through a
-complete cube representations, in a way similar to what Cube Explorer does.
-This used to be different before version 2.1 (June 2022).
-
-More documentation on this and on the different types of coordinates (base
-vs composed) is work in progress.
-
-### Solving
-
-Solving is implemented as a generic function that takes both a step and
-a (scrambled) cube as input, as well as some extra parameters that say e.g.
-how many solution one wants. A step consists, among other things, of
-an estimator function that, given a cube, gives a lower bound for the number
-of moves needed to complete the step. Many of these estimators simply
-look up the corresponding values in the appropriate pruning table.
-
+# Work in progress
diff --git a/TODO.md b/TODO.md
@@ -1,142 +0,0 @@
-# TODO list
-
-This is a list of things that I would like to add or change at some point.
-It's more of a personal reminder than anything else.
-
-## For version 2.1
-### Slow: it is slower than the old nissy 2.0.2 :(
-* nxopt's trick (switching to reduce branching) actually saves about 50%!
-* Another factor is estimating *while* moving (i.e. do not move all
- coordinates if the first one already gives a high value!)
-* simplify solve, remove everything that is used only by optimal solvers
-* Good compromise: each stepalt offers one of two alternatives: either solve
- by simply using pruning tables and moving coordinates, or using a custom
- estimator and moving a cube (or fast_cube) and computing coordinates
- in the estimator
-* is there really no way to use inverse branching trick with current system?
-* new file optimal.c with the old solve logic; try first with the simple
- cube implementation and the new indexers, if it is still slow change
- to fast_cube (intermediate nissy v2.0.2 implementation)
-### Changes to Step and Solve
-* remove cube from dfsarg? (i still need to save the scramble somewhere,
- but I really only use it in dfs_niss)
-* coord.c: all old coordinates (WIP...)
-* steps.c: checkers (use coordinates), all stepalt and steps (WIP...)
-* commands gen and freemem
-* commands.c: twophase, ...?
-* Coordinate should have a moveset field? No, at worst there are some garbage
- values in mtable, but no risk for errors
-### Rotate, not transform, before solving
-* solve should re-orient first if needed and not just give up if centers are off
-### Documentation
-* Document how coordinates and pruning tables work now
-* Write an examples.md file
-* More screenshots!
-### Tables management
-* Check files in tables directory automatically remove old / extraneous files
-* Add checksum to check that tables are generated / downloaded correctly
-### Conditional compiling
-* Option to avoid large tables at compile time
-* option to avoid multithreading (write a simpler solve for t=1, and also
- check if found enough solutions before checking pruning values)
-### Technical
-* generic option parser
-* testing? Maybe just hardcode some examples generated with old nissy
-### Commands
-* Easy: add option -I (inverse) and -L (linear, like inverse + normal)
- to do only linear NISS
-
-## Commands
-
-### Commands that are available in nissy 1.0, but not in this version (yet):
-* drcorners (solve corners after dr)
-* search and improve non-optimal subsequences
-* save and edit algs as "variables"
- (or just use a "logging system" to keep info about previously run commands,
-including e.g. solutions that were not shown because -c)
-
-### More steps for `solve`
-* QTM optimal solving
-* 5-side solve (for robots)
-* Block-building steps (cross, roux blocks, ...)
-* Other common steps (LSE, ...)
-* Larger table for drudfin (include epe)? About 1Gb uncompressed,
- 500Mb compressed (fallback to noE), 250 compressed + parity trick
- (is it doable?)
-
-### Improvements to currently implemented commands
-* solve multidfs: do multithread by step, not by alternative (this way
- if there are multiple alternatives it can make use of more threads)
-* solve should try up to a small bound without loading the large pruning table
- (maybe this is not necessary if loading the table is fast enough)
-* silent batch mode without >>>
-
-### New features
-* EO analysis (and also DR and HTR analysis): group similar EOs together
- and such (suggested by Jay)
-* configurability: add an `alias` command, run config file at startup
-* command notation to list available moves
-* make multi-step solve much more general and create command
-* input directly cube status instead of moves
- (graphical: maybe there is a cubing.js function; command line: ???)
-
-## Distribution
-* webapp (cgi)
-
-## Technical stuff
-
-### Testing
-* write some proper tests, move test_coord to the testing module(s)
-
-### Memory management
-* free pruning table after solve is done? if I do this I need to deafault to a
- small table for < 8 moves solutions or smth
-* improve multi-threading when solving multiple scrambles
-* nissy -M maxmem option for running with at most maxmem memory; if exceeded
- when loading a pruning table, return failure (or make every solve command
- use tiny tables instead?); if maxmem is very 600Mb or
- less do not use invtables (the performance loss is minimal anyway). If the
- limit is really tiny, do not use mtables or ttables (but this would be
- very slow and probably nobody will ever use it)
-* Check if memory is enough for loading pruning tables; if not, abort
-* For optimal solver: choose largest that fits in memory between nxopt and light
-
-### Structural changes
-* client/server architecture: run a server process in the background so that
- multiple client processess can send it queries and get results; this would
- open up the door for a web-based version or graphical clients
-
-### Cleanup
-* sort again functions alphabetically in their files
-* change some function and variable names to make everything consistent
-* more stuff to load at start (or when suitable command is called) rather
- than when called directly, to avoid nasty problems with threading
-* parse command args: one function per arg type, then each command has
- a list of options that it accepts (as a string)
-
-### Style
-* do not declare all variables at the beginning of a function
-* remove var names from prototypes
-* various stuff from style(9)
-
-### Random
-Collect random info like this somewhere:
-
-Table pt_nxopt31_HTM
-Base value: 9
-0 1
-1 6
-2 29
-3 164
-4 1433
-5 16772
-6 205033
-7 2513871
-8 30329976
-9 342440769
-10 2815191126
-11 6147967200
-12 524918774
-13 3546
-14 0
-15 0
diff --git a/main.c b/main.c
diff --git a/old/maybe-useful-coord.c b/old/maybe-useful-coord.c
@@ -1,181 +0,0 @@
-int
-array_ep_to_epos(int *ep, int *ss)
-{
- int epos[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- int eps[4];
- int i, j, is;
-
- for (i = 0, is = 0; i < 12; i++) {
- for (j = 0; j < 4; j++) {
- if (ep[i] == ss[j]) {
- eps[is++] = j;
- epos[i] = 1;
- }
- }
- }
-
- for (i = 0; i < 4; i++)
- swap(&epos[ss[i]], &epos[i+8]);
-
- return 24 * subset_to_index(epos, 12, 4) + perm_to_index(eps, 4);
-}
-
-void
-epos_to_compatible_ep(int epos, int *ep, int *ss)
-{
- int i, j, k, other[8];
- bool flag;
-
- for (i = 0; i < 12; i++)
- ep[i] = -1;
-
- epos_to_partial_ep(epos, ep, ss);
-
- for (i = 0, j = 0; i < 12; i++) {
- flag = false;
- for (k = 0; k < 4; k++)
- flag = flag || (i == ss[k]);
- if (!flag)
- other[j++] = i;
- }
-
- for (i = 0, j = 0; i < 12; i++)
- if (ep[i] == -1)
- ep[i] = other[j++];
-}
-
-void
-epos_to_partial_ep(int epos, int *ep, int *ss)
-{
- int i, is, eposs[12], eps[4];
-
- index_to_perm(epos % FACTORIAL4, 4, eps);
- index_to_subset(epos / FACTORIAL4, 12, 4, eposs);
-
- for (i = 0; i < 4; i++)
- swap(&eposs[ss[i]], &eposs[i+8]);
-
- for (i = 0, is = 0; i < 12; i++)
- if (eposs[i])
- ep[i] = ss[eps[is++]];
-}
-
-void
-fix_eorleoud(CubeArray *arr)
-{
- int i;
-
- for (i = 0; i < 12; i++) {
- if ((edge_slice(i) == 0 && edge_slice(arr->ep[i]) != 0) ||
- (edge_slice(i) != 0 && edge_slice(arr->ep[i]) == 0)) {
- arr->eorl[i] = 1 - arr->eofb[i];
- } else {
- arr->eorl[i] = arr->eofb[i];
- }
-
- if ((edge_slice(i) == 2 && edge_slice(arr->ep[i]) != 2) ||
- (edge_slice(i) != 2 && edge_slice(arr->ep[i]) == 2)) {
- arr->eoud[i] = 1 - arr->eofb[i];
- } else {
- arr->eoud[i] = arr->eofb[i];
- }
- }
-}
-
-void
-fix_cofbcorl(CubeArray *arr)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- if (i % 2 == arr->cp[i] % 2) {
- arr->cofb[i] = arr->coud[i];
- arr->corl[i] = arr->coud[i];
- } else {
- if (arr->cp[i] % 2 == 0) {
- arr->cofb[i] = (arr->coud[i]+1)%3;
- arr->corl[i] = (arr->coud[i]+2)%3;
- } else {
- arr->cofb[i] = (arr->coud[i]+2)%3;
- arr->corl[i] = (arr->coud[i]+1)%3;
- }
- }
- }
-}
-
-Cube
-admissible_ep(Cube cube, PieceFilter f)
-{
- CubeArray *arr = new_cubearray(cube, f);
- Cube ret;
- bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- int i, j;
-
- for (i = 0; i < 12; i++)
- if (arr->ep[i] != -1)
- used[arr->ep[i]] = true;
-
- for (i = 0, j = 0; i < 12; i++) {
- for ( ; j < 11 && used[j]; j++);
- if (arr->ep[i] == -1)
- arr->ep[i] = j++;
- }
-
- ret = arrays_to_cube(arr, pf_ep);
- free_cubearray(arr, f);
-
- return ret;
-}
-
-int
-edge_slice(Edge e) {
- if (e < 0 || e > 11)
- return -1;
-
- if (e == FR || e == FL || e == BL || e == BR)
- return 0;
- if (e == UR || e == UL || e == DR || e == DL)
- return 1;
-
- return 2;
-}
-
-int
-piece_orientation(Cube cube, int piece, char *orientation)
-{
- int arr[12], n, b, x;
-
- if (!strcmp(orientation, "eofb")) {
- x = cube.eofb;
- n = 12;
- b = 2;
- } else if (!strcmp(orientation, "eorl")) {
- x = cube.eorl;
- n = 12;
- b = 2;
- } else if (!strcmp(orientation, "eoud")) {
- x = cube.eoud;
- n = 12;
- b = 2;
- } else if (!strcmp(orientation, "coud")) {
- x = cube.coud;
- n = 8;
- b = 3;
- } else if (!strcmp(orientation, "corl")) {
- x = cube.corl;
- n = 8;
- b = 3;
- } else if (!strcmp(orientation, "cofb")) {
- x = cube.cofb;
- n = 8;
- b = 3;
- } else {
- return -1;
- }
-
- int_to_sum_zero_array(x, b, n, arr);
- if (piece < n)
- return arr[piece];
-
- return -1;
-}
diff --git a/old/maybe-useful-steps.c b/old/maybe-useful-steps.c
@@ -1,1111 +0,0 @@
-#include "steps.h"
-
-#define UPDATECHECKSTOP(a, b, c) if ((a=(MAX((a),(b))))>(c)) return (a);
-
-static int estimate_stepalt(StepAlt *a, uint64_t *ind);
-
-/* Checkers and validators ***************************************************/
-
-/* TODO: these should be with Cube *cube (and all need to change) */
-/* Maybe move them to cube.c */
-static bool check_centers(Cube cube);
-static bool check_coud_HTM(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_eofb(Cube cube);
-static bool check_drud(Cube cube);
-static bool check_htr(Cube cube);
-
-static bool always_valid(Alg *alg);
-static bool validate_singlecw_ending(Alg *alg);
-
-/* Messages for when cube is not ready ***************************************/
-
-static char check_centers_msg[100] = "cube must be oriented (centers solved)";
-static char check_eo_msg[100] = "EO must be solved on given axis";
-static char check_dr_msg[100] = "DR must be solved on given axis";
-static char check_htr_msg[100] = "HTR must be solved";
-static char check_drany_msg[100] = "DR must be solved on at least one axis";
-
-/* Steps *********************************************************************/
-
-/* Optimal solvers *******************/
-
-Step
-optimal_HTM = {
- .shortname = "optimal",
- .name = "Optimal solve (in HTM)",
-
- .final = true,
- .is_done = is_solved,
- .estimate = estimate_nxopt31_HTM,
- .ready = check_centers,
- .ready_msg = check_centers_msg,
- .is_valid = always_valid,
- .moveset = &moveset_HTM,
-
- .pre_trans = uf,
-
- .tables = {&pd_nxopt31_HTM, &pd_corners_HTM},
- .ntables = 2,
-};
-
-Step
-optimal_light_HTM = {
- .shortname = "light",
- .name = "Optimal solve (in HTM), small table (500Mb RAM total)",
-
- .final = true,
- .is_done = is_solved,
- .estimate = estimate_light_HTM,
- .ready = check_centers,
- .ready_msg = check_centers_msg,
- .is_valid = always_valid,
- .moveset = &moveset_HTM,
-
- .pre_trans = uf,
-
- .tables = {&pd_drud_sym16_HTM, &pd_corners_HTM},
- .ntables = 2,
-};
-
-/* Optimal after EO ******************/
-
-Step
-eofin_eo = {
- .shortname = "eofin",
- .name = "Optimal solve after EO without breaking EO (detected)",
-
- .final = true,
- .is_done = is_solved,
- .estimate = estimate_nxopt31_HTM,
- .ready = check_eofb,
- .ready_msg = check_eo_msg,
- .is_valid = always_valid,
- .moveset = &moveset_eofb,
-
- .detect = detect_pretrans_eofb,
-
- .tables = {&pd_nxopt31_HTM, &pd_corners_HTM},
- .ntables = 2,
-};
-
-Step
-eofbfin_eofb = {
- .shortname = "eofbfin",
- .name = "Optimal after EO on F/B without breaking EO",
-
- .final = true,
- .is_done = is_solved,
- .estimate = estimate_nxopt31_HTM,
- .ready = check_eofb,
- .ready_msg = check_eo_msg,
- .is_valid = always_valid,
- .moveset = &moveset_eofb,
-
- .pre_trans = uf,
-
- .tables = {&pd_nxopt31_HTM, &pd_corners_HTM},
- .ntables = 2,
-};
-
-Step
-eorlfin_eorl = {
- .shortname = "eorlfin",
- .name = "Optimal after EO on R/L without breaking EO",
-
- .final = true,
- .is_done = is_solved,
- .estimate = estimate_nxopt31_HTM,
- .ready = check_eofb,
- .ready_msg = check_eo_msg,
- .is_valid = always_valid,
- .moveset = &moveset_eofb,
-
- .pre_trans = ur,
-
- .tables = {&pd_nxopt31_HTM, &pd_corners_HTM},
- .ntables = 2,
-};
-
-Step
-eoudfin_eoud = {
- .shortname = "eoudfin",
- .name = "Optimal after EO on U/D without breaking EO",
-
- .final = true,
- .is_done = is_solved,
- .estimate = estimate_nxopt31_HTM,
- .ready = check_eofb,
- .ready_msg = check_eo_msg,
- .is_valid = always_valid,
- .moveset = &moveset_eofb,
-
- .pre_trans = fd,
-
- .tables = {&pd_nxopt31_HTM, &pd_corners_HTM},
- .ntables = 2,
-};
-
-/* EO steps **************************/
-Step
-eoany_HTM = {
- .shortname = "eo",
- .name = "EO on any axis",
-
- .final = false,
- .is_done = check_eofb,
- .estimate = estimate_eofb_HTM,
- .ready = check_centers,
- .ready_msg = check_centers_msg,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_HTM,
-
- .detect = detect_pretrans_void_3axis,
-
- .tables = {&pd_eofb_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_HTM,
-
- .pre_trans = uf,
-
- .tables = {&pd_eofb_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_HTM,
-
- .pre_trans = ur,
-
- .tables = {&pd_eofb_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_HTM,
-
- .pre_trans = fd,
-
- .tables = {&pd_eofb_HTM},
- .ntables = 1,
-};
-
-/* CO steps **************************/
-Step
-coany_HTM = {
- .shortname = "co",
- .name = "CO on any axis",
-
- .final = false,
- .is_done = check_coud_HTM,
- .estimate = estimate_coud_HTM,
- .ready = NULL,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_HTM,
-
- .detect = detect_pretrans_void_3axis,
-
- .tables = {&pd_coud_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .moveset = &moveset_HTM,
-
- .pre_trans = uf,
-
- .tables = {&pd_coud_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .moveset = &moveset_HTM,
-
- .pre_trans = rf,
-
- .tables = {&pd_coud_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .moveset = &moveset_HTM,
-
- .pre_trans = fd,
-
- .tables = {&pd_coud_HTM},
- .ntables = 1,
-};
-
-Step
-coany_URF = {
- .shortname = "co-URF",
- .name = "CO any axis (URF moveset)",
-
- .final = false,
- .is_done = check_coud_URF,
- .estimate = estimate_coud_URF,
- .ready = NULL,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_URF,
-
- .detect = detect_pretrans_void_3axis,
-
- .tables = {&pd_coud_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .moveset = &moveset_URF,
-
- .pre_trans = uf,
-
- .tables = {&pd_coud_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .moveset = &moveset_URF,
-
- .pre_trans = rf,
-
- .tables = {&pd_coud_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .moveset = &moveset_URF,
-
- .pre_trans = fd,
-
- .tables = {&pd_coud_HTM},
- .ntables = 1,
-};
-
-/* Misc corner steps *****************/
-Step
-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,
- .moveset = &moveset_HTM,
-
- .pre_trans = uf,
-
- .tables = {&pd_cornershtr_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .moveset = &moveset_URF,
-
- .pre_trans = uf,
-
- .tables = {&pd_cornershtr_HTM},
- .ntables = 1,
-};
-
-Step
-corners_HTM = {
- .shortname = "corners",
- .name = "Solve corners",
-
- .final = true,
- .is_done = check_corners_HTM,
- .estimate = estimate_corners_HTM,
- .ready = NULL,
- .is_valid = always_valid,
- .moveset = &moveset_HTM,
-
- .pre_trans = uf,
-
- .tables = {&pd_corners_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .moveset = &moveset_URF,
-
- .pre_trans = uf,
-
- .tables = {&pd_corners_HTM},
- .ntables = 1,
-};
-
-/* DR steps **************************/
-Step
-drany_HTM = {
- .shortname = "dr",
- .name = "DR on any axis",
-
- .final = false,
- .is_done = check_drud,
- .estimate = estimate_drud_HTM,
- .ready = check_centers,
- .ready_msg = check_centers_msg,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_HTM,
-
- .detect = detect_pretrans_void_3axis,
-
- .tables = {&pd_drud_sym16_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_HTM,
-
- .pre_trans = uf,
-
- .tables = {&pd_drud_sym16_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_HTM,
-
- .pre_trans = rf,
-
- .tables = {&pd_drud_sym16_HTM},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_HTM,
-
- .pre_trans = fd,
-
- .tables = {&pd_drud_sym16_HTM},
- .ntables = 1,
-};
-
-/* DR from EO */
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_eofb,
-
- .detect = detect_pretrans_eofb,
-
- .tables = {&pd_drud_eofb},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_eofb,
-
- .pre_trans = uf,
-
- .tables = {&pd_drud_eofb},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_eofb,
-
- .pre_trans = ur,
-
- .tables = {&pd_drud_eofb},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_eofb,
-
- .pre_trans = fd,
-
- .tables = {&pd_drud_eofb},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_eofb,
-
- .pre_trans = uf,
-
- .tables = {&pd_drud_eofb},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_eofb,
-
- .pre_trans = rf,
-
- .tables = {&pd_drud_eofb},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_eofb,
-
- .pre_trans = ur,
-
- .tables = {&pd_drud_eofb},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_eofb,
-
- .pre_trans = fr,
-
- .tables = {&pd_drud_eofb},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_eofb,
-
- .pre_trans = fd,
-
- .tables = {&pd_drud_eofb},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_eofb,
-
- .pre_trans = rd,
-
- .tables = {&pd_drud_eofb},
- .ntables = 1,
-};
-
-/* DR finish steps */
-Step
-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,
- .is_valid = always_valid,
- .moveset = &moveset_drud,
-
- .detect = detect_pretrans_drud,
-
- .tables = {&pd_drudfin_noE_sym16_drud},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = always_valid,
- .moveset = &moveset_drud,
-
- .pre_trans = uf,
-
- .tables = {&pd_drudfin_noE_sym16_drud},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = always_valid,
- .moveset = &moveset_drud,
-
- .pre_trans = rf,
-
- .tables = {&pd_drudfin_noE_sym16_drud},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = always_valid,
- .moveset = &moveset_drud,
-
- .pre_trans = fd,
-
- .tables = {&pd_drudfin_noE_sym16_drud},
- .ntables = 1,
-};
-
-/* HTR from DR */
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_drud,
-
- .detect = detect_pretrans_drud,
-
- .tables = {&pd_htr_drud},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_drud,
-
- .pre_trans = uf,
-
- .tables = {&pd_htr_drud},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_drud,
-
- .pre_trans = rf,
-
- .tables = {&pd_htr_drud},
- .ntables = 1,
-};
-
-Step
-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,
- .is_valid = validate_singlecw_ending,
- .moveset = &moveset_drud,
-
- .pre_trans = fd,
-
- .tables = {&pd_htr_drud},
- .ntables = 1,
-};
-
-/* HTR finish */
-Step
-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,
- .is_valid = always_valid,
- .moveset = &moveset_htr,
-
- .pre_trans = uf,
-
- .tables = {&pd_htrfin_htr},
- .ntables = 1,
-};
-
-Step *steps[] = {
- &optimal_HTM, /* first is default */
- &optimal_light_HTM,
-
- &eofin_eo,
- &eofbfin_eofb,
- &eorlfin_eorl,
- &eoudfin_eoud,
-
- &eoany_HTM,
- &eofb_HTM,
- &eorl_HTM,
- &eoud_HTM,
-
- &coany_HTM,
- &coud_HTM,
- &corl_HTM,
- &cofb_HTM,
-
- &coany_URF,
- &coud_URF,
- &corl_URF,
- &cofb_URF,
-
- &drany_HTM,
- &drud_HTM,
- &drrl_HTM,
- &drfb_HTM,
-
- &dr_eo,
- &dr_eofb,
- &dr_eorl,
- &dr_eoud,
- &drud_eofb,
- &drrl_eofb,
- &drud_eorl,
- &drfb_eorl,
- &drfb_eoud,
- &drrl_eoud,
-
- &dranyfin_DR,
- &drudfin_drud,
- &drrlfin_drrl,
- &drfbfin_drfb,
-
- &htr_any,
- &htr_drud,
- &htr_drrl,
- &htr_drfb,
-
- &htrfin_htr,
-
- &cornershtr_HTM,
- &cornershtr_URF,
- &corners_HTM,
- &corners_URF,
-
- NULL
-};
-
-/* Checkers and validators ***************************************************/
-
-static bool
-check_centers(Cube cube)
-{
- return cube.cpos == 0;
-}
-
-static bool
-check_coud_HTM(Cube cube)
-{
- return cube.coud == 0;
-}
-
-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_eofb(Cube cube)
-{
- return cube.eofb == 0;
-}
-
-static bool
-check_drud(Cube cube)
-{
- return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0;
-}
-
-static bool
-check_htr(Cube cube)
-{
- return check_drud(cube) && coord_htr_drud.index(cube) == 0;
-}
-
-static bool
-always_valid(Alg *alg)
-{
- return true;
-}
-
-static bool
-validate_singlecw_ending(Alg *alg)
-{
- int i;
- bool nor, inv;
- Move l2 = NULLMOVE, l1 = NULLMOVE, l2i = NULLMOVE, l1i = NULLMOVE;
-
- for (i = 0; i < alg->len; i++) {
- if (alg->inv[i]) {
- l2i = l1i;
- l1i = alg->move[i];
- } else {
- l2 = l1;
- l1 = alg->move[i];
- }
- }
-
- nor = l1 ==base_move(l1) && (!commute(l1, l2) ||l2 ==base_move(l2));
- inv = l1i==base_move(l1i) && (!commute(l1i,l2i)||l2i==base_move(l2i));
-
- return nor && inv;
-}
-
-/* Public functions **********************************************************/
-
-void
-compute_ind(StepAlt *a, Cube *cube, uint64_t *ind)
-{
-
-}
-
-int
-estimate_stepalt(StepAlt *a, uint64_t *ind)
-{
- int i, ret, est[a->n_coord];
-
- for (i = 0; i < a->n_coord; i++) {
- est[i] = ptableval(a->pd[i], ind[i]);
- if (est[i] == 0 && a->compact_pd[i])
- est[i] = ptableval(a->fallback_pd, ind[i] / a->fbmod);
- }
-
- for (i = 0; i < a->n_dbtrick; i++)
- if (est[a->dbtrick[i][0]] == est[a->dbtrick[i][1]] &&
- est[a->dbtrick[i][0]] == est[a->dbtrick[i][2]])
- est[a->dbtrick[i][0]] += 1;
-
- for (i = 0, ret = -1; i < a->n_coord; i++)
- ret = max(ret, est[i]);
-
- return ret;
-}
-
-void
-prepare_step(Step *step, SolveOptions *opts)
-{
- int i, j;
- PDGenData pdg;
- StepAlt *a;
-
- init_moveset(step->moveset);
- pdg.moveset = step->moveset;
-
- for (i = 0; step->alt[i] != NULL; i++) {
- a = step->alt[i];
- for (j = 0; j < a->n_coord; j++) {
- gen_coord(a->coord[j]);
-
- pdg.coord = a->coord[j];
- pdg.compact = a->compact[j];
- pdg.pd = NULL;
-
- a->pd[j] = genptable(&pdg, opts->nthreads);
-
- if (a->compact_pd[j]) {
- gen_coord(a->fallback_coord[j]);
-
- pdg.coord = a->fallback_coord[j];
- pdg.compact = false;
- pdg.pd = NULL;
-
- a->fallback_pd[j] =
- step->genptable(&pdg, opts->nthreads);
- }
- }
- }
-}
diff --git a/www/download/index.html b/www/download/index.html
@@ -1,212 +0,0 @@
-<!doctype html>
-<html lang="en">
-<head>
- <title> Download | Nissy </title>
-<meta name="viewport" content="width=device-width" /> <link rel="stylesheet" type="text/css" href="/style-3.css">
- <link rel="icon" href="/favicon.png">
- <meta charset="utf-8">
-</head>
-
-<body>
-
-<nav class="top">
- <table class="menu">
- <tr>
- <td class="logo"> <a href="/"><img src="/favicon.png" alt="logo"></a> </td>
- <td class="links">
- <a href="/download/">Download</a> |
- <a href="/examples/">Examples</a>
- </td>
- </tr>
- </table>
-</nav>
-
-<hr class="line">
-
-
-<h1>Get Nissy</h1>
-
-<table class="dltable">
-<tr>
- <td></td>
- <td><strong>Source code</strong></td>
- <td><strong>Windows executable</strong></td>
-</tr>
-<tr>
- <td><strong>Latest version</strong></td>
- <td><a href="/nissy-2.0.2.tar.gz">nissy-2.0.2.tar.gz (67Kb)</a></td>
- <td><a href="/nissy-2.0.2.exe">nissy-2.0.2.exe (780Kb)</a></td>
-</tr>
-</table>
-
-<p>
-In this page you can find download links (see above),
-<a href="#Installation">installation instructions</a> and
-<a href="#Upgrade">upgrade instructions</a>
-for nissy. If instead you wish to clone the
-<a href="https://git.tronto.net/nissy/">git repository</a>,
-you can use git:
-</p>
-
-<pre>
-<code>git clone https://git.tronto.net/nissy</code>
-</pre>
-
-<p>
-For a summary of changes and a list of older versions see below. Some versions
-(for example 1.0) are not available directly, but can be obtained from
-the git repository.
-</p>
-
-<h2 id="Installation">Installation</h2>
-
-<h3>System requirements</h3>
-
-<p>
-A full installation of nissy requires about 3.1Gb of space,
-of which 2.3Gb are occupied by the huge pruning table for fast optimal solving,
-and running it requires the same amount of RAM.
-One can choose to never use this function and not to install the relative
-pruning table. There is an alternative (slower)
-optimal solving function that uses about 500Mb of RAM.
-
-When generating the pruning tables automatically (see the section Tables below),
-at least 5.3Gb or RAM are required.
-</p>
-
-<h3>Windows</h3>
-
-<p>
-Try downloading and executing in a terminal the file <code>nissy.exe</code>,
-then follow the instructions in the <strong>Tables</strong> section below for
-installing the pruning tables.
-If <code>nissy.exe</code> does not work, you can try following the UNIX instructions
-in WSL (Windows Subsystem for Linux) or in a similar environment.
-</p>
-
-<h3>UNIX (Linux, MacOS, *BSD...)</h3>
-<p>
-Download the source archive (.tar.gz). Extract it
-with your favorite archive program, for example with
-</p>
-<pre><code>tar -xvzf nissy-VERSION.tar.gz</code></pre>
-<p>
-Open a terminal in the directory just extracted.
-If you wish, edit the <code>Makefile</code> to match your local configuration
-(this is usually not necessary, but you may want to change the
-<code>PREFIX</code> variable to change the installation path) and run
-<pre><code>make</code></pre>
-<p>
-followed by
-</p>
-<pre><code>make install</code></pre>
-<p>
-Then follow the instructions below to install the pruning tables.
-</p>
-
-<h3>Tables</h3>
-
-<p>
-Once you have installed nissy, run
-</p>
-
-<pre><code>nissy gen</code></pre>
-
-<p>
-to generate all the tables that Nissy will ever need.
-Running this command requires around 5.3Gb of RAM, and it can take some time
-(about 40 minutes on my fairly old but decent laptop, with 8 CPU threads).
-</p>
-
-<p>
-Some unnecessary technical detail: by default this command is going to use
-at most 64 threads. If you want you can choose to use more threads (if your CPU
-is very powerful) or fewer threads (if you for example want to run this command
-in the background while you do other stuff) with the <code>-t</code> option, for
-example <code>nissy gen -t 1</code>.
-</p>
-
-<p>
-Alternatively, you can
-<a href="/nissy-tables-2.0.2.zip">download all the tables (1.7Gb)</a> and
-copy them into the correct folder (see manual page, <code>ENVIRONMENT</code>
-section). On UNIX operating systems this folder is either
-<code>.nissy/tables</code> in the user's home directory or
-<code>$XDG_DATA_HOME/nissy/tables</code> if the XDG variable is configured.
-On Windows it is the same directory as the <code>nissy.exe</code> executable
-file.
-</p>
-
-<h2 id="Upgrade">Upgrading</h2>
-<p>
-If you already have nissy installed and you want to upgrade to a more
-recent version, you can simply repeat the installation process:
-</p>
-<ul>
-<li>
-On Windows: simply replace nissy.exe with the new file with the same name.
-</li>
-<li>
-On UNIX systems: download the new version of the source code, extract it in
-a new folder and run <code>make</code> and <code>make install</code> again.
-</li>
-</ul>
-<p>
-Between each version new table files might have been added, or old ones
-may be not used anymore. Nissy will deal with this automatically.
-</p>
-
-<h2>Version history</h2>
-
-<h3>Nissy v2</h3>
-
-<table class=dltable>
-<tr>
- <td><strong>Version</strong></td>
- <td><strong>Date</strong></td>
- <td><strong>Comment</strong></td>
-</tr>
-<tr>
- <td><a href="/nissy-2.0.2.tar.gz">2.0.2</a></td>
- <td>2022-06-01</td>
- <td>Improved table generation speed</td>
-</tr>
-<tr>
- <td><a href="/nissy-2.0.1.tar.gz">2.0.1</a></td>
- <td>2022-02-22</td>
- <td>Bugfix release</td>
-</tr>
-<tr>
- <td>2.0</td>
- <td>2021-12-29</td>
- <td>Rewritten from scratch; much faster optimal solver</td>
-</tr>
-</table>
-
-<h3>Nissy v1</h3>
-
-<p>
-Nissy v1 was released in 2020. It was slow, full of bugs and the code
-was quite terrible. But in practice it got its job done most of the time.
-</p>
-
-
-<hr class="line">
-
-<nav class="bottom">
- <table class="footer">
- <tr>
- <td class="contact">
- <a href="https://sebastiano.tronto.net">sebastiano.tronto.net</a>
- </td>
- <td class="hosted">
- <a href="mailto:sebastiano@tronto.net">
- sebastiano@tronto.net
- </a>
- </td>
- </tr>
- </table>
-</nav>
-
-</body>
-</html>
diff --git a/www/examples/index.html b/www/examples/index.html
@@ -1,49 +0,0 @@
-<!doctype html>
-<html lang="en">
-<head>
- <title> Examples | Nissy </title>
-<meta name="viewport" content="width=device-width" /> <link rel="stylesheet" type="text/css" href="/style-3.css">
- <link rel="icon" href="/favicon.png">
- <meta charset="utf-8">
-</head>
-
-<body>
-
-<nav class="top">
- <table class="menu">
- <tr>
- <td class="logo"> <a href="/"><img src="/favicon.png" alt="logo"></a> </td>
- <td class="links">
- <a href="/download/">Download</a> |
- <a href="/examples/">Examples</a>
- </td>
- </tr>
- </table>
-</nav>
-
-<hr class="line">
-
-
-<h1>Examples</h1>
-
-(Coming soon...)
-
-<hr class="line">
-
-<nav class="bottom">
- <table class="footer">
- <tr>
- <td class="contact">
- <a href="https://sebastiano.tronto.net">sebastiano.tronto.net</a>
- </td>
- <td class="hosted">
- <a href="mailto:sebastiano@tronto.net">
- sebastiano@tronto.net
- </a>
- </td>
- </tr>
- </table>
-</nav>
-
-</body>
-</html>
diff --git a/www/favicon.png b/www/favicon.png
Binary files differ.
diff --git a/www/index.html b/www/index.html
@@ -1,93 +0,0 @@
-<!doctype html>
-<html lang="en">
-<head>
- <title> Nissy | Nissy </title>
-<meta name="viewport" content="width=device-width" /> <link rel="stylesheet" type="text/css" href="/style-3.css">
- <link rel="icon" href="/favicon.png">
- <meta charset="utf-8">
-</head>
-
-<body>
-
-<nav class="top">
- <table class="menu">
- <tr>
- <td class="logo"> <a href="/"><img src="/favicon.png" alt="logo"></a> </td>
- <td class="links">
- <a href="/download/">Download</a> |
- <a href="/examples/">Examples</a>
- </td>
- </tr>
- </table>
-</nav>
-
-<hr class="line">
-
-
-<h1>Nissy</h1>
-
-<p class=subtitle>A Rubik's cube solver and FMC assistant</p>
-
-<img src="/screenshot.png" alt="A screenshot of nissy running in a terminal emulator">
-
-<p>
-Nissy is a command-line Rubik's cube solver. It can find optimal solutions
-for random positions using techniques from Herbert Kociemba's
-<a href="http://kociemba.org/cube.htm">Cube Explorer</a> and
-Tomas Rokicki's
-<a href="https://github.com/rokici/cube20src/blob/master/nxopt.md">nxopt</a>.
-With 4 cores at 2.5GHz and using about 3Gb of RAM, Nissy can find an optimal
-solution in about a minute on average.
-</p>
-
-<p>
-Nissy aims at being a complete tool
-for FMC (Fewest Moves Challenge) practice. It can solve different steps
-of Thistlethwaite's algorithm (also know as DR/HTR) and cans use NISS
-(Normal-Inverse Scramble Switch).
-</p>
-
-<p>
-You should use Nissy if:
-</p>
-<ul>
-<li>
-You want to analyze your DR solutions or check for multiple optimal
-(or sub-optimal) solutions for EO/DR/HTR or similar steps.
-</li>
-<li>
-You just want a Rubik's cube solver and you like command line interfaces.
-</li>
-<li>
-You want an alternative to Cube Explorer.
-</li>
-</ul>
-
-<p>
-To get started, head to the <a href="/download/">download</a> page.
-</p>
-
-<p>
-You can also see its source code by cloning the git repository
-<a href="https://git.tronto.net/nissy/">git.tronto.net/nissy</a>
-</p>
-
-<hr class="line">
-
-<nav class="bottom">
- <table class="footer">
- <tr>
- <td class="contact">
- <a href="https://sebastiano.tronto.net">sebastiano.tronto.net</a>
- </td>
- <td class="hosted">
- <a href="mailto:sebastiano@tronto.net">
- sebastiano@tronto.net
- </a>
- </td>
- </tr>
- </table>
-</nav>
-
-</body>
-</html>
diff --git a/www/screenshot.png b/www/screenshot.png
Binary files differ.
diff --git a/www/style-2.css b/www/style-2.css
@@ -1,105 +0,0 @@
-.menu {
- width: 100%;
-}
-
-.links {
- text-align: right;
- font-weight: bold;
-}
-
-.logo img {
- width: 50px;
- height: 50px;
-}
-
-.footer {
- font-style: italic;
- width: 100%;
-}
-
-.hosted {
- text-align: right;
-}
-
-body {
- margin: auto 8px 20px 8px;
-}
-
-img {
- display: block;
- margin-left: auto;
- margin-right: auto;
- max-width: 100%;
-}
-
-code {
- background-color: #eeeeee;
- padding: 2px;
-}
-
-pre code {
- padding: 0px;
-}
-
-pre {
- background-color: #eeeeee;
- border: 2px solid;
- padding: 6px;
-}
-
-#blob {
- background: #ffffff;
- border: none;
-}
-
-a {
- color: #0f2899;
- text-decoration: none;
-}
-
-.links a {
- font-weight: bold;
- color: black;
-}
-
-.hosted a,
-.contact a {
- font-weight: bold;
-}
-
-a:hover {
- text-decoration: underline;
-}
-
-html {
- margin: 1em auto;
- max-width: 42em;
-}
-
-h1 {
- text-align: center;
-}
-
-td h1 {
- text-align: left;
- font-size: 1.5em;
-}
-
-table {
- width: 100%;
-}
-
-.url td {
- font-family: monospace;
-}
-
-.dltable th, .dltable td {
- border: 1px solid black;
- padding: 3px;
-}
-
-.subtitle {
- text-align: center;
- font-weight: bold;
- font-size: 1.1em;
-}