nissy-nx

A Rubik's cube optimal solver
git clone https://git.tronto.net/nissy-nx
Download | Log | Files | Refs | README | LICENSE

commit aca0f840a85e1b6642b7d8876ad21e6430bf1feb
parent 7184160f0806eb8be1a4944e2b3b1c5b86d9e995
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date:   Wed, 13 Sep 2023 19:07:18 +0200

Some cleanup

Diffstat:
DINSTALL | 81-------------------------------------------------------------------------------
MMakefile | 39++-------------------------------------
MREADME.md | 30++++++++++++++++++++++++++++++
DTODO/2.1.md | 55-------------------------------------------------------
DTODO/build-options.md | 33---------------------------------
DTODO/documentation.md | 41-----------------------------------------
DTODO/easy.md | 16----------------
DTODO/installation.md | 14--------------
DTODO/new-feature-ideas.md | 32--------------------------------
DTODO/parser.md | 13-------------
DTODO/refactoring.md | 41-----------------------------------------
DTODO/testing.md | 6------
DTODO/webapp.md | 19-------------------
Ddoc/nissy.1 | 271-------------------------------------------------------------------------------
Dold/maybe-useful-coord.c | 181-------------------------------------------------------------------------------
Dold/maybe-useful-steps.c | 1111-------------------------------------------------------------------------------
Msrc/commands.c | 257+------------------------------------------------------------------------------
Msrc/commands.h | 128++-----------------------------------------------------------------------------
Msrc/coord.h | 4----
Msrc/shell.c | 37-------------------------------------
Dsrc/solver_step.c | 306-------------------------------------------------------------------------------
Dsrc/solver_step.h | 12------------
Dsrc/steps.c | 177-------------------------------------------------------------------------------
Dsrc/steps.h | 243-------------------------------------------------------------------------------
Dwww/download/index.html | 217-------------------------------------------------------------------------------
Dwww/examples/index.html | 49-------------------------------------------------
Dwww/favicon.png | 0
Dwww/index.html | 93-------------------------------------------------------------------------------
Dwww/screenshot.png | 0
Dwww/style-3.css | 105-------------------------------------------------------------------------------
30 files changed, 35 insertions(+), 3576 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 @@ -29,41 +29,6 @@ test: ${CC} ${DBGFLAGS} -DTEST -o test src/*.c tests/*.c clean: - rm -rf nissy nissy*.exe nissy*.tar.gz doc/nissy.html doc/nissy.pdf + rm -rf nissy nissy.exe -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 test clean dist install uninstall upload +.PHONY: all debug test clean diff --git a/README.md b/README.md @@ -4,3 +4,33 @@ Work in progress, need to clean up and fix. This is an optimal solver only, for other versions see [nissy](https://git.tronto.net/nissy). + +TODO: document things that have been lost in the split to nissy-classic. + +* Coordinates +* Symcoordinates (new stuff!) +* Pruning tables (maybe not necessary) +* Coordinate solving +* fst cube +* Is it worth saving optimal solver stuff (threader...)? + +Where to collect random information like this table? + +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/TODO/2.1.md b/TODO/2.1.md @@ -1,55 +0,0 @@ -# TODO-list for version 2.1 (or is it 3.0 at this point?) - -## Rework solver - -### 1. Implement minimum viable - -* Check current optimal implementation (implement command, this is not step) -* Save old pruning values in cubedata -* Implement branch switching -* Get rid of useless allocations, pass empty pointer and copy there - -### 2. Rework achitecture and file dependencies - -* solve.h depends only on moves(alg?) (dependency on step and trans is removed). -* Other modules have changed dependencies, might as well rework all. -* Make files smaller, do not include definition in .h, separate -data from abstract operations. -* remove cubetypes.h -* Create a module for multi-step (maybe wait?) -* Possible changes: in step solver, copy cube only if niss; add cleanup function -in solver (called by solve()) to free cube and perhaps pruning tables. -* see various TODO's in files - -### 3. More threading options - -* Lazy multithread: threads are as independent as possible and only -merged at the end. Ideal when all solutions of a certain length are requested. -* (Done) Eager multithread: current implementation, branches communicate the -number and list of solutions to stop as soon as possible. Good when only one -solution of a certain depth is required. - -## Simplify steps - -* Remove one type of rotation. -* Change steps to choicestep and stepalt to step (or was this already done?). -* Maybe: split optimal solver to a completely different module. This allows - for good semplification on the main generic solver (e.g. get rid of - move_check_stop). To be evaluated in terms of performance gain and actual - simplification (might not be much for either). - -## Add missing coordinates and steps - -* Check the old file for a list. Many are missing. -* Checkers in steps.c should use coordinates. - -## Missing and new commands - -* gen -* freemem -* twophase - -## Easy improvements - -* Solve should re-orient the cube if centers are off -* Solve: add options for -I (inverse only) and -L (linear = normal + inverse). diff --git a/TODO/build-options.md b/TODO/build-options.md @@ -1,33 +0,0 @@ -# Build options for memory and multithreading - -## Investigate - -* Check exactly how much memory is needed for everything. -* Take note of which parts use threading (solving, genptable, other?). - -## Prepare code - -* Use define / ifdef or similar to compile and build tables only for the - parts to be used. -* If threads = 1, use a much simpler version of the solve method. Remember - that checking if enough solutions have been found is the first thing to - do in singlethread (no locking). -* Do not include pthread if threads = 1. -* Only one optimal solver should be compiled. -* Some simple steps may also need alternatives with smaller tables - (e.g. for staying sub 1Gb). For example dr and drfin. -* If necessary, work out alternatives to "twophase" for low-resource versions. - -## Makefile - -* Figure out how to change these options via makefile. For example: one - variable for the maximum allowed ram and one for the number of threads. -* (Optional) use a configure script? -* (Optional) interactive installation script? - -## Automate - -* Scout for resources during installation and choose best configuration - automatically. -* How to do this in Linux / POSIX? -* How to do this in Windows? diff --git a/TODO/documentation.md b/TODO/documentation.md @@ -1,41 +0,0 @@ -# Documentation - -## Big documentation file on nissy's internals - -* Coordinates -* Symcoordinates -* Pruning tables -* Coordinate solving -* fst cube -* Optimized solver -* Multithreading -* Commands etc... -* Code architecture - -## examples.md - -* Example file for nissy's website and documentation folder -* With screenshots! - -## Random info - -Where to collect random information like this table? - -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/TODO/easy.md b/TODO/easy.md @@ -1,16 +0,0 @@ -# Easy things to improve or add - -## Improvements - -* Silent batch mode without >>> -* Solutions should be shown sorted: by length first, then by normal moves - (no niss) first, then it depends on the step (e.g. EO by axis). - -## Old commands and steps - -* drcorners (solve corners after DR) -* Search and improve suboptimal subsequences - -## New commands - -* notation: show valid moves diff --git a/TODO/installation.md b/TODO/installation.md @@ -1,14 +0,0 @@ -# Simplify and improve installation - -## Tables - -* Make install should generate tables, or add a "make tables" target to - generate tables. -* Make tables should also check for existing files and remove old ones - (maybe more for nissy's command than for makefile). - -## Correctness - -* Add checksum for all generated files. -* Hard-code results? Check for compatibility problems between different OSes - and filesystems - but there should not be any, since we use stdint.h. diff --git a/TODO/new-feature-ideas.md b/TODO/new-feature-ideas.md @@ -1,32 +0,0 @@ -# Possible new features and improvements - -This file contains non-refined ideas. Once an idea gets refined, it will -get its own file and more details. - -## Steps - -* QTM solver -* 5-side solver (for robots) -* Other steps (cross, blocks, LSE...) - -## UX features - -* Save algs as variables and edit them (like in old nissy) -* Use a logging system for previously run commands, info, results... - (e.g. when solving with -c solutions are not shown, they can be logged here) -* Configurability: add an "alias" command, run config file at startup -* Input cube state directly instead of moves (ugly from command line / file) - -## Improvements - -* Optimal solver: when asking only for one solution, scan for upper bound in - parallel using a non-optimal (but fast) solver (e.g. twophase). -* Optimal solver: up to a small bound, try with a small pruning table. -* Optimal solver: start at different depths in parallel -* Multi-step solver: make more general - -## New features - -* Allow user to specify moveset manually (see issue \#5 on github) -* EO analysis (and also DR and HTR analysis): group similar EOs (Jay) -* HTR "maze" analysis? diff --git a/TODO/parser.md b/TODO/parser.md @@ -1,13 +0,0 @@ -# Improve command parser - -First, expand this TODO file to be more precise. - -## Refactor - -* The syntax of a command's options should be described by data, not by a - parser function. -* A single parser function can then parse options for all commands. - -## Usability - -* Better error messages! diff --git a/TODO/refactoring.md b/TODO/refactoring.md @@ -1,41 +0,0 @@ -# Refactoring - -## Init functions - -* All .h files should have a single init function. -* This function should initialize everything that this module needs, including - calling the init functions of the modules it depends on. -* To avoid multiple initialization of the same module, each should have a - static bool initialized variable. -* Everything that a module needs should be initialized by init(), avoid - initializing stuff when solving. Exception: pruning tables, move tables. -* Most functions should generate some tables and save them to disk. -* Init functions should have a consistent structure (e.g. the way they check - if the tables are already generated should be the same). - -## Cube types - -* Get rid of cubetype.h, split type definitionss into the other modules. -* Every type definition should be in the most fundamental module that needs it. - -## Code style - -* Use goto for error handling (if needed) -* Headers: blank line between <> and "" includes -* Remove variable names from prototypes (debatable). -* Stop declaring all variables at the beginning of a function (debatable). -* Rename functions and variable to have a consistent naming scheme. -* Sort functions: prototypes in logical blocks, then alphabetic. - Implementations in the same order as the prototypes. -* Order of variable declarations (in files, functions and structs): - Size first (large to small), then alphabetic. -* Indent: make second level indent consistent to 4 spaces. - Try to avoid long statements. -* Avoid include statements in .h files, use ifdef guards in .c files - (to reconsider as part of the redesign). -* Functions that copy data: swap src and dest, follow memcpy standard. - -## Generic - -* Avoid malloc and free/new function pointers for cube objects, - use array of char on stack. diff --git a/TODO/testing.md b/TODO/testing.md @@ -1,6 +0,0 @@ -# Testing - -## Write tests - -* Write tests for each module. Some of might require refactoring (this is - a good thing!) diff --git a/TODO/webapp.md b/TODO/webapp.md @@ -1,19 +0,0 @@ -# Towards a nissy webapp - -## Architecture - -* Split in client / server. -* Server can load and keep in memory all the tables, client(s) send messages to - the server to run commands. -* Use UNIX sockets only first, maybe later try WinSock. - -## Simple webapp - -* Investigate how to use fastcgi, try simple program first. -* Decide what limits to put in terms of resources and write a "filter" script - to block big requests (maybe use a timeout). - -## Advanced webapp - -* Use cubing.js for nice graphics. -* Port it to a graphical desktop version too. diff --git a/doc/nissy.1 b/doc/nissy.1 @@ -1,271 +0,0 @@ -.Dd November 2021 -.Dt NISSY 1 -.Os -.Sh NAME -.Nm nissy -.Nd a Rubik's cube solver and FMC assistant -. -.Sh SYNOPSIS -.Nm -.Op Fl b -.Nm -.Ar command -.Op options... -. -.Sh DESCRIPTION -.Nm -is a Rubik's Cube solver. -It uses techniques from Herbert Kociemba's Cube Explorer and -Tomas Rokicki's nxopt. With 4 cores at 2.5GHz and using about 3Gb -of RAM, Nissy can find the optimal solution for a random Rubik's cube position -in about a minute on average. -Nissy can also solve different substeps of the Thistlethwaite's algorithm and more. -.Pp -When run without any argument an interactive shell is launched, otherwise -the provided -.Ar command -is executed and nissy terminates. If the option -.Fl b -is given, every argument after it is ignored and the shell is launched without -any prompt or welcome message. This can be used to run nissy in batch mode, -for example writing a list of commands in a -.Ar file -(one per line) and running -.Ar nissy -b < file -.Pp -The commands that can be run in the interactive shell are the same that can -be run non-interactively and are provided below. -. -.Sh COMMANDS -The available -.Ar commands -are the following: -. -.Bl -tag -width Ds -. -.It Nm cleanup Ar scramble -Rewrites the given scramble using only the 18 base (HTM) moves and at most two -rotations at the end. If -Ar scramble -uses NISS, all moves done on normal scramble are written first, followed by -all moves done on inverse. -. -.It Nm commands -List all available commands. -. -.It Nm freemem -Release some large tables from memory. You can use this command in case -you want to keep nissy open without using too much RAM. -. -.It Nm gen Op Fl t Ar N -Generate all tables used by nissy. Run this to complete your installation. -If -.Ar N -is specified, -.Ar N -CPU threads will be used (defaults to 64, use less only if you don't want -nissy to use all of your CPU resources). -. -.It Nm help Op Ar command -Display help. If no -.Ar command -is given, a generic help message is printed, otherwise a specific help -relative to -.Ar command -is returned. -. -.It Nm invert Ar scramble -Invert the given scramble. -. -.It Nm print Ar scramble -Display a text-only description of the cube obtained after applying -.Ar scramble . -. -.It Nm quit -Quit nissy. -. -.It Nm scramble Oo Fl n Ar N Oc Oo Ar type Oc -Print a randomly-generated (random position) scramble -. -If -.Ar N -is given, it produces -.Ar N -scrambles. -.Ar type -can be specified to be one of the following: -.Bl -tag -width Ds -.It Ar corners -Scramble with solved edges (only cornes are scrambled). -.It Ar dr -Scramble with solved DR on U/D. -.It Ar edges -Scramble with solved corners (only edges are scrambled). -.It Ar eo -Scramble with solved EO on F/B axis. -.It Ar fmc -Scramble the full cube and the resulting scramble starts and ends with -the moves R\(aq U\(aq F. -.It Ar htr -Scramble with HTR solved. -.El -. -.It Nm solve Ar step Oo Ar options Oc Ar scramble -Solve the given -.Ar step -on the given -.Ar scramble. -By default it finds only one (shortest) solution, without using niss, and it -displays the number of moves at the end of the line. -. -The options for the -.Ar solve -command are the following: -. -.Bl -tag -width Ds -. -.It Fl a -Print all solutions: some solutions are filtered out by default for some -steps, for examples EOs that finish with F\(aq, with this options they are not. -. -.It Fl c -Display only the number of solutions found, not the solutions themselves. -. -.It Fl m Ar min -Only look for solution that are at least -.Ar min -moves long. -. -.It Fl M Ar MAX -Only look for solution that are at most -.Ar MAX -moves long. -. -.It Fl n Ar N -Try to find -.Ar N -solutions. By default and unless the -.Fl M -or -.Fl o -options are used, at most one solution is returned. -If at least one of -.Fl M -and -.Fl o -is used, all the solutions found within the given bounds are returned. -The option -.Fl s -overwrites these default behaviors and at most -.Ar N -solutions are returned, still satisfiyng the other constraints. -. -.It Fl N -Allow use of NISS. -. -.It Fl o -Only find solutions that require the minimum number of moves. -. -.It Fl O Ar N -Only find solutions that require at most -.Ar N -moves more than the optimal solution. If -.Ar N -is 0, this is equivalent to -.Fl o -. -.It Fl p -Plain style: do not print the number of moves. -. -.It Fl t Ar N -Use -.Ar N -CPU threads. By default nissy uses only 1 thread. Using more than one -thread will improve performance, but the optimal number depends on your -machine and operating system. Generally, using one less than the number -of threads of your CPU works quite well. -. -.It Fl v -Verbose mode: print some information during the search and print each solution -as it is found instead of only printing them all together at the end. -. -. -.El -. -.It Nm steps -List all available -.Ar steps -for the -.Ar solve -command. -. -.It Nm twophase Ar scramble -Find a solution using a two-phase method. This does not guarantee -to return an optimal solution (and in fact most often it does not), -but it is very fast. -. -.It Nm unniss Ar scramble -Rewrite the scramble without using NISS. -. -.It Nm version -Display version information. -. -.El -. -.Sh SCRAMBLES -All the commands above that accept a scramble also accept a -.Fl Nm i -option with no arguments. -If this option is given, multiple scrambles are read from standard -input (one per line) until and EOF is found, at which point stdin is cleared. -. -.Sh ENVIRONMENT -Data is stored in the folder pointed to by -.Nm $NISSYDATA. -If that variable is unset the folder -.Nm $XDG_DATA_HOME/nissy -or -.Nm $HOME/.nissy -is used instead. If none of this environment variables is defined -(e.g. in a non-UNIX system), the current folder is used. -. -.Sh EXAMPLES -.Pp -The command: -.Dl nissy solve -v -O 1 \(dqR\(aqU\(aqFD2L2FR2U2R2BD2LB2D\(aqB2L\(aqR\(aqBD2BU2LU2R\(aqU\(aqF\(dq -Returns: -.Dl Searching depth 0 -.Dl Searching depth 1 -.Dl (some more lines) -.Dl Searching depth 16 -.Dl D2 F\(aq U2 D2 F\(aq L2 D R2 D F B2 R\(aq L2 F\(aq U\(aq D -.Dl Searching depth 17 -.Dl D2 F\(aq U2 D2 F\(aq L2 D R2 D F B2 R\(aq L2 F\(aq U\(aq D (16) -Notice that the solution is printed twice: the first time it is printed as soon -as it is found as requested by the -v option. -.Pp -The command: -.Dl nissy solve eofb -m 4 -M 5 -N -n 6 \(dqR\(aqU\(aqFD2L2 FR2 U2R2BD2 L B2 D\(aq B2 L\(aq R\(aq\(dq -Returns: -.Dl U B U\(aq B (4) -.Dl U (B R\(aq B) (4) -.Dl (U B R\(aq B) (4) -.Dl U2 F R2 F (4) -.Dl U2 B U2 B (4) -.Dl (U2 B R\(aq B) (4) -.Pp -On a UNIX shell, the composite command -.Dl nissy scramble -n 2 | nissy solve -i > file.txt -Generates two random scrambles, solves them and saves the result to file.txt. -The file will look something like this: -.Dl >>> Line: D U2 F D B\(aq F L2 D\(aq F2 R2 L B2 L\(aq U2 B2 R F2 L\(aq D2 -.Dl U2 R2 F2 L B2 D\(aq R2 D\(aq F U L2 B\(aq U\(aq R2 D2 R2 U (17) -.Dl >>> Line: D B R U\(aq B\(aq L2 U L U D2 R L B2 U2 L2 U2 R U2 B2 L F2 -.Dl D\(aq F R\(aq D B L2 B R2 L U L U2 B D\(aq U R U F2 (18) -. -.Sh AUTHORS -.An Sebastiano Tronto Aq Mt sebastiano@tronto.net -. -.Sh SOURCE CODE -Source code is available at -.Lk https://nissy.tronto.net 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/src/commands.c b/src/commands.c @@ -2,8 +2,6 @@ #include "commands.h" -static bool read_cs(CommandArgs *args, char *str); -static bool read_scrtype(CommandArgs *args, char *str); static bool read_scramble(int c, char **v, CommandArgs *args); /* Arg parsing functions implementation **************************************/ @@ -83,8 +81,6 @@ solve_parse_args(int c, char **v) } a->opts->optimal = val; infinitesols = true; - } else if (!strcmp(v[i], "-N")) { - a->opts->can_niss = true; } else if (!strcmp(v[i], "-i")) { a->scrstdin = true; } else if (!strcmp(v[i], "-v")) { @@ -95,8 +91,6 @@ solve_parse_args(int c, char **v) a->opts->print_number = false; } else if (!strcmp(v[i], "-c")) { a->opts->count_only = true; - } else if (!read_cs(a, v[i])) { - break; } } @@ -108,36 +102,6 @@ solve_parse_args(int c, char **v) } CommandArgs * -scramble_parse_args(int c, char **v) -{ - int i; - long val; - - CommandArgs *a = new_args(); - - a->success = true; - a->n = 1; - - for (i = 0; i < c; i++) { - if (!strcmp(v[i], "-n") && i+1 < c) { - val = strtol(v[++i], NULL, 10); - if (val < 1 || val > 1000000) { - fprintf(stderr, - "Invalid number of scrambles.\n"); - a->success = false; - return a; - } - a->n = val; - } else if (!read_scrtype(a, v[i])) { - a->success = false; - return a; - } - } - - return a; -} - -CommandArgs * gen_parse_args(int c, char **v) { int val; @@ -246,95 +210,6 @@ solve_exec(CommandArgs *args) } void -scramble_exec(CommandArgs *args) -{ - Cube cube; - Alg *scr, *ruf, *aux; - int i, j, eo, ep, co, cp; - uint64_t ui, uj, uk; - - srand(time(NULL)); - - for (i = 0; i < args->n; i++) { - - if (!strcmp(args->scrtype, "dr")) { - ui = rand() % FACTORIAL8; - uj = rand() % FACTORIAL8; - uk = rand() % FACTORIAL4; - - make_solved(&cube); - index_to_perm(ui, 8, cube.cp); - index_to_perm(uj, 8, cube.ep); - index_to_perm(uk, 4, cube.ep + 8); - for (j = 8; j < 12; j++) - cube.ep[j] += 8; - } else if (!strcmp(args->scrtype, "htr")) { - make_solved(&cube); - /* TODO */ - } else { - ep = rand() % FACTORIAL12; - cp = rand() % FACTORIAL8; - eo = rand() % POW2TO11; - co = rand() % POW3TO7; - - if (!strcmp(args->scrtype, "eo")) { - eo = 0; - } else if (!strcmp(args->scrtype, "corners")) { - eo = 0; - ep = 0; - } else if (!strcmp(args->scrtype, "edges")) { - co = 0; - cp = 0; - } - - make_solved(&cube); - index_to_perm(ep, 12, cube.ep); - index_to_perm(cp, 8, cube.cp); - int_to_sum_zero_array(eo, 2, 12, cube.eo); - int_to_sum_zero_array(co, 3, 8, cube.co); - } - - if (!is_admissible(&cube)) { - if (!strcmp(args->scrtype, "corners")) - swap(&cube.cp[UFR], &cube.cp[UFL]); - else - swap(&cube.ep[UF], &cube.ep[UB]); - } - - /* TODO: can be optimized for htr and dr using htrfin, drfin */ - /* - TODO: solve_2phase was removed - scr = solve_2phase(&cube, 1); - */ - - if (!strcmp(args->scrtype, "fmc")) { - aux = new_alg(""); - copy_alg(scr, aux); - /* Trick to rufify for free: rotate the scramble * - * so that it does not start with F or end with R */ - for (j = 0; j < NROTATIONS; j++) { - if (base_move(scr->move[0]) != F && - base_move(scr->move[0]) != B && - base_move(scr->move[scr->len-1]) != R && - base_move(scr->move[scr->len-1]) != L) - break; - copy_alg(aux, scr); - transform_alg(j, scr); - } - copy_alg(scr, aux); - ruf = new_alg("R' U' F"); - copy_alg(ruf, scr); - compose_alg(scr, aux); - compose_alg(scr, ruf); - free_alg(aux); - free_alg(ruf); - } - print_alg(scr, false); - free_alg(scr); - } -} - -void gen_exec(CommandArgs *args) { /* TODO: @@ -350,76 +225,6 @@ gen_exec(CommandArgs *args) } void -invert_exec(CommandArgs *args) -{ - Alg *inv; - - inv = inverse_alg(args->scramble); - print_alg(inv, false); - - free_alg(inv); -} - -void -steps_exec(CommandArgs *args) -{ - int i; - - for (i = 0; csteps[i] != NULL; i++) - printf("%-15s %s\n", csteps[i]->shortname, csteps[i]->name); -} - -void -commands_exec(CommandArgs *args) -{ - int i; - - for (i = 0; commands[i] != NULL; i++) - printf("%s\n", commands[i]->usage); - -} - -void -freemem_exec(CommandArgs *args) -{ -/* TODO: - int i; - - for (i = 0; all_pd[i] != NULL; i++) - free_pd(all_pd[i]); - - for (i = 0; all_sd[i] != NULL; i++) - free_sd(all_sd[i]); -*/ -} - -void -print_exec(CommandArgs *args) -{ - Cube c; - - make_solved(&c); - apply_alg(args->scramble, &c); - print_cube(&c); -} - -/* -void -twophase_exec(CommandArgs *args) -{ - Cube c; - Alg *sol; - - make_solved(&c); - apply_alg(args->scramble, &c); - sol = solve_2phase(&c, 1); - - print_alg(sol, false); - free_alg(sol); -} -*/ - -void help_exec(CommandArgs *args) { if (args->command == NULL) { @@ -447,33 +252,6 @@ quit_exec(CommandArgs *args) exit(0); } -void -cleanup_exec(CommandArgs *args) -{ - Alg *alg; - - alg = cleanup(args->scramble); - print_alg(alg, false); - - free_alg(alg); -} - -void -unniss_exec(CommandArgs *args) -{ - Alg *aux; - - aux = unniss(args->scramble); - print_alg(aux, false); - free(aux); -} - -void -version_exec(CommandArgs *args) -{ - printf(VERSION"\n"); -} - /* Local functions implementation ********************************************/ static bool @@ -507,38 +285,6 @@ read_scramble(int c, char **v, CommandArgs *args) return args->scramble->len > 0; } -static bool -read_scrtype(CommandArgs *args, char *str) -{ - int i; - static char *scrtypes[20] = - { "eo", "corners", "edges", "fmc", "dr", "htr", NULL }; - - for (i = 0; scrtypes[i] != NULL; i++) { - if (!strcmp(scrtypes[i], str)) { - strcpy(args->scrtype, scrtypes[i]); - return true; - } - } - - return false; -} - -static bool -read_cs(CommandArgs *args, char *str) -{ - int i; - - for (i = 0; csteps[i] != NULL; i++) { - if (!strcmp(csteps[i]->shortname, str)) { - args->cs = csteps[i]; - return true; - } - } - - return false; -} - /* Public functions implementation *******************************************/ void @@ -567,8 +313,7 @@ new_args() args->scramble = NULL; /* initialized in read_scramble */ args->opts = malloc(sizeof(SolveOptions)); - /* step and command are static */ - args->cs = csteps[0]; /* default: first step in list */ + args->cs = NULL; args->command = NULL; return args; diff --git a/src/commands.h b/src/commands.h @@ -4,8 +4,6 @@ #include <time.h> #include "solve.h" -#include "steps.h" -#include "solver_step.h" #include "solver_nxopt31.h" #include "threader_single.h" #include "threader_eager.h" @@ -20,42 +18,22 @@ CommandArgs * help_parse_args(int c, char **v); CommandArgs * parse_only_scramble(int c, char **v); CommandArgs * parse_no_arg(int c, char **v); CommandArgs * solve_parse_args(int c, char **v); -CommandArgs * scramble_parse_args(int c, char **v); /* Exec functions ************************************************************/ void gen_exec(CommandArgs *args); -void cleanup_exec(CommandArgs *args); -void invert_exec(CommandArgs *args); void solve_exec(CommandArgs *args); -void scramble_exec(CommandArgs *args); -void steps_exec(CommandArgs *args); -void commands_exec(CommandArgs *args); -void freemem_exec(CommandArgs *args); -void print_exec(CommandArgs *args); -/*void twophase_exec(CommandArgs *args);*/ void help_exec(CommandArgs *args); void quit_exec(CommandArgs *args); -void unniss_exec(CommandArgs *args); -void version_exec(CommandArgs *args); /* Commands ******************************************************************/ #ifndef COMMANDS_C -extern Command cleanup_cmd; -extern Command commands_cmd; -extern Command freemem_cmd; extern Command gen_cmd; extern Command help_cmd; -extern Command invert_cmd; -extern Command print_cmd; extern Command quit_cmd; -extern Command scramble_cmd; extern Command solve_cmd; -extern Command steps_cmd; -extern Command unniss_cmd; -extern Command version_cmd; extern Command *commands[]; @@ -64,22 +42,13 @@ extern Command *commands[]; Command solve_cmd = { .name = "solve", - .usage = "solve STEP [OPTIONS] SCRAMBLE", - .description = "Solve a step; see command steps for a list of steps", + .usage = "solve [OPTIONS] SCRAMBLE", + .description = "Solve the cube", .parse_args = solve_parse_args, .exec = solve_exec }; Command -scramble_cmd = { - .name = "scramble", - .usage = "scramble [TYPE] [-n N]", - .description = "Get a random-position scramble", - .parse_args = scramble_parse_args, - .exec = scramble_exec, -}; - -Command gen_cmd = { .name = "gen", .usage = "gen [-t N]", @@ -89,51 +58,6 @@ gen_cmd = { }; Command -invert_cmd = { - .name = "invert", - .usage = "invert SCRAMBLE]", - .description = "Invert a scramble", - .parse_args = parse_only_scramble, - .exec = invert_exec, -}; - -Command -steps_cmd = { - .name = "steps", - .usage = "steps", - .description = "List available steps", - .parse_args = parse_no_arg, - .exec = steps_exec -}; - -Command -commands_cmd = { - .name = "commands", - .usage = "commands", - .description = "List available commands", - .parse_args = parse_no_arg, - .exec = commands_exec -}; - -Command -freemem_cmd = { - .name = "freemem", - .usage = "freemem", - .description = "free large tables from RAM", - .parse_args = parse_no_arg, - .exec = freemem_exec, -}; - -Command -print_cmd = { - .name = "print", - .usage = "print SCRAMBLE", - .description = "Print written description of the cube", - .parse_args = parse_only_scramble, - .exec = print_exec, -}; - -Command help_cmd = { .name = "help", .usage = "help [COMMAND]", @@ -142,17 +66,6 @@ help_cmd = { .exec = help_exec, }; -/* -Command -twophase_cmd = { - .name = "twophase", - .usage = "twophase", - .description = "Find a solution quickly using a 2-phase method", - .parse_args = parse_only_scramble, - .exec = twophase_exec, -}; -*/ - Command quit_cmd = { .name = "quit", @@ -162,48 +75,11 @@ quit_cmd = { .exec = quit_exec, }; -Command -cleanup_cmd = { - .name = "cleanup", - .usage = "cleanup SCRAMBLE", - .description = "Rewrite a scramble using only standard moves (HTM)", - .parse_args = parse_only_scramble, - .exec = cleanup_exec, -}; - -Command -unniss_cmd = { - .name = "unniss", - .usage = "unniss SCRAMBLE", - .description = "Rewrite a scramble without NISS", - .parse_args = parse_only_scramble, - .exec = unniss_exec, -}; - -Command -version_cmd = { - .name = "version", - .usage = "version", - .description = "print nissy version", - .parse_args = parse_no_arg, - .exec = version_exec, -}; - Command *commands[] = { - &commands_cmd, - &freemem_cmd, &gen_cmd, &help_cmd, - &invert_cmd, - &print_cmd, &quit_cmd, &solve_cmd, - &scramble_cmd, - &steps_cmd, -/* &twophase_cmd,*/ - &cleanup_cmd, - &unniss_cmd, - &version_cmd, NULL }; diff --git a/src/coord.h b/src/coord.h @@ -27,10 +27,6 @@ extern Coordinate coord_epud; extern Coordinate coord_eofbepos; extern Coordinate coord_coud_cpudsep; extern Coordinate coord_eofbepos_sym16; -extern Coordinate coord_cp_sym16; -extern Coordinate coord_corners_sym16; -extern Coordinate coord_drud_sym16; -extern Coordinate coord_drudfin_noE_sym16; extern Coordinate coord_nxopt31; extern Coordinate *all_coordinates[]; diff --git a/src/shell.c b/src/shell.c @@ -5,30 +5,6 @@ static void cleanwhitespaces(char *line); static int parseline(char *line, char **v); -bool -checkfiles() -{ - /* TODO: add more checks (other files, use checksum...) */ - /* How to check for pruning tables with new method? */ - /* Solution: use list of steps */ - /* - char fname[strlen(tabledir)+100]; - int i; - - for (i = 0; all_pd[i] != NULL; i++) { - strcpy(fname, tabledir); - strcat(fname, "/"); - strcat(fname, all_pd[i]->filename); - if ((f = fopen(fname, "rb")) == NULL) - return false; - else - fclose(f); - } - */ - - return true; -} - static void cleanwhitespaces(char *line) { @@ -146,20 +122,9 @@ launch(bool batchmode) int main(int argc, char *argv[]) { - char *closing_cmd[1] = { "freemem" }; - init_env(); init_trans(); - if (!checkfiles()) { - fprintf(stderr, - "--- Warning ---\n" - "Some pruning tables are missing or unreadable\n" - "You can generate them with `nissy gen'.\n" - "---------------\n\n" - ); - } - if (argc > 1) { if (!strcmp(argv[1], "-b")) { launch(true); @@ -170,8 +135,6 @@ main(int argc, char *argv[]) launch(false); } - exec_args(1, closing_cmd); - return 0; } #endif diff --git a/src/solver_step.c b/src/solver_step.c @@ -1,306 +0,0 @@ -#include "solver_step.h" - -typedef struct { - Cube * cube; - uint64_t * val; - Trans * t; -} CubeData; - -static void apply_move_cubedata(void *, void *, Move); -static void init_indexes(Step *, CubeData *); -static void * prepare_cube(void *, Cube *); -static bool move_check_stop_eager(void *, DfsArg *, Threader *); -static bool move_check_stop_lazy(void *, DfsArg *, Threader *); -static bool move_check_stop_nonsol(void *, DfsArg *, Threader *); -static bool is_solved_step(void *, void *); -static Alg * validate_solution(void *, Alg *); -static void * alloc_cubedata(void *); -static void copy_cubedata(void *, void *, void *); -static void free_cubedata(void *, void *); -static void invert_cubedata(void *, void *); -static bool niss_makes_sense(void *, void *, Alg *); -static Solver * new_stepsolver_nocheckstop(Step *step); - -static void -apply_move_cubedata(void *param, void *cubedata, Move m) -{ - Step *s = (Step *)param; - CubeData *data = (CubeData *)cubedata; - - Trans tt; - for (int i = 0; i < s->n_coord; i++) { - Move mm = transform_move(data->t[i], m); - data->val[i] = move_coord(s->coord[i], mm, data->val[i], &tt); - data->t[i] = transform_trans(tt, data->t[i]); - } -} - -static void -init_indexes(Step *step, CubeData *data) -{ - int i; - Cube moved; - Trans t, tt; - - for (i = 0; i < step->n_coord; i++) { - t = step->coord_trans[i]; - copy_cube(data->cube, &moved); - apply_trans(t, &moved); - data->val[i] = index_coord(step->coord[i], &moved, &tt); - data->t[i] = transform_trans(tt, t); - } -} - -static void * -prepare_cube(void *param, Cube *cube) -{ - int i; - Step *s; - CubeData *data; - - s = (Step *)param; - - for (i = 0; i < s->n_coord; i++) { - s->pd[i] = malloc(sizeof(PruneData)); - s->pd[i]->moveset = s->moveset; -/* TODO: check if moveset initialization works fine, - e.g. if there is a variable to save the initialized status - or if it gets initialized multiple times */ - init_moveset(s->moveset); - s->pd[i]->coord = s->coord[i]; - gen_coord(s->coord[i]); - s->pd[i]->compact = s->pd_compact[i]; - s->pd[i] = genptable(s->pd[i], 4); /* TODO: threads */ - } - - data = alloc_cubedata(param); - data->cube = malloc(sizeof(Cube)); - copy_cube(cube, data->cube); - init_indexes(s, data); - - return data; -} - -static bool -move_check_stop_eager(void *param, DfsArg *arg, Threader *threader) -{ - int nsol; - - if (move_check_stop_nonsol(param, arg, threader)) - return true; - - nsol = threader->get_nsol(arg->threaddata); - return nsol >= arg->opts->max_solutions; -} - -static bool -move_check_stop_lazy(void *param, DfsArg *arg, Threader *threader) -{ - int nsol; - - nsol = threader->get_nsol(arg->threaddata); - if (nsol >= arg->opts->max_solutions) - return true; - - return move_check_stop_nonsol(param, arg, threader); -} - -/* TODO: split in 2 (nissable / non-nissable) and only move cube - when nissable */ -static bool -move_check_stop_nonsol(void *param, DfsArg *arg, Threader *threader) -{ - int i, goal, bound; - Move mm, lastmove; - Trans tt = uf; - CubeData *data; - Step *s; - - s = (Step *)param; - data = (CubeData *)arg->cubedata; - - - bound = 0; - goal = arg->d - arg->current_alg->len; -/* TODO: check if len is 0 */ - lastmove = arg->current_alg->move[arg->current_alg->len-1]; - for (i = 0; i < s->n_coord; i++) { - mm = transform_move(data->t[i], lastmove); - data->val[i] = move_coord(s->coord[i], mm, data->val[i], &tt); - data->t[i] = transform_trans(tt, data->t[i]); - - bound = MAX(bound, ptableval(s->pd[i], data->val[i])); - if (arg->opts->can_niss && !arg->niss) - bound = MIN(1, bound); - - if (bound > goal) { - return true; - } - } - if (arg->opts->can_niss && !arg->niss) - apply_move(lastmove, data->cube); - - return false; -} - -static bool -is_solved_step(void *param, void *cubedata) -{ - int i; - Step *s; - CubeData *data; - - s = (Step *)param; - data = (CubeData *)cubedata; - - for (i = 0; i < s->n_coord; i++) - if (data->val[i] != 0) - return false; - - return true; -} - -static Alg * -validate_solution(void *param, Alg *alg) -{ - return ((Step *)param)->is_valid(alg); -} - -static void * -alloc_cubedata(void *param) -{ - Step *s; - CubeData *data; - - s = (Step *)param; - - data = malloc(sizeof(CubeData)); - /* We do not need to allocate a cube */ - data->val = malloc(s->n_coord * sizeof(uint64_t)); - data->t = malloc(s->n_coord * sizeof(Trans)); - - return data; -} - -static void -copy_cubedata(void *param, void *src, void *dst) -{ - int i; - Step *s; - CubeData *newdata, *olddata; - - s = (Step *)param; - olddata = (CubeData *)src; - newdata = (CubeData *)dst; - -/* TODO: do not copy if not nissable */ - newdata->cube = malloc(sizeof(Cube)); - copy_cube(olddata->cube, newdata->cube); - for (i = 0; i < s->n_coord; i++) { - newdata->val[i] = olddata->val[i]; - newdata->t[i] = olddata->t[i]; - } -} - -static void -free_cubedata(void *param, void *cubedata) -{ - CubeData *data; - - data = (CubeData *)cubedata; - - free(data->t); - free(data->val); - free(data->cube); - free(data); -} - -static void -invert_cubedata(void *param, void *cubedata) -{ - Step *s; - CubeData *data; - - s = (Step *)param; - data = (CubeData *)cubedata; - - invert_cube(data->cube); - init_indexes(s, data); -} - -static bool -niss_makes_sense(void *param, void *cubedata, Alg *alg) -{ - Step *s; - CubeData *data; - - s = (Step *)param; - data = (CubeData *)cubedata; - - if (s->final) - return false; - - if (alg->len_normal == 0) - return true; - - Move m = inverse_move(alg->move_normal[alg->len_normal-1]); - for (int i = 0; i < s->n_coord; i++) { - Move mm = transform_move(data->t[i], m); - uint64_t u = move_coord(s->coord[i], mm, 0, NULL); - if (ptableval(s->pd[i], u) > 0) - return true; - } - - return false; -} - -static Solver * -new_stepsolver_nocheckstop(Step *step) -{ - Solver *solver; - - solver = malloc(sizeof(Solver)); - - solver->moveset = step->moveset; - solver->param = step; - - solver->apply_move = apply_move_cubedata; - solver->prepare_cube = prepare_cube; - solver->is_solved = is_solved_step; - solver->validate_solution = validate_solution; - solver->alloc_cubedata = alloc_cubedata; - solver->copy_cubedata = copy_cubedata; - solver->free_cubedata = free_cubedata; - solver->invert_cube = invert_cubedata; - solver->niss_makes_sense = niss_makes_sense; - - return solver; -} - -Solver * -new_stepsolver_eager(Step *step) -{ - Solver *solver; - - solver = new_stepsolver_nocheckstop(step); - solver->move_check_stop = move_check_stop_eager; - - return solver; -} - -Solver * -new_stepsolver_lazy(Step *step) -{ - Solver *solver; - - solver = new_stepsolver_nocheckstop(step); - solver->move_check_stop = move_check_stop_lazy; - - return solver; -} - -void -free_stepsolver(Solver *solver) -{ - free(solver); -} diff --git a/src/solver_step.h b/src/solver_step.h @@ -1,12 +0,0 @@ -#ifndef SOLVER_STEP_H -#define SOLVER_STEP_H - -#include "cube.h" -#include "solve.h" -#include "steps.h" - -Solver *new_stepsolver_eager(Step *); -Solver *new_stepsolver_lazy(Step *); -void free_stepsolver(Solver *); - -#endif diff --git a/src/steps.c b/src/steps.c @@ -1,177 +0,0 @@ -#define STEPS_C - -#include "steps.h" - -/* TODO: change all checkers to use coordinates! */ - -bool -check_centers(Cube *cube) -{ - int i; - - for (i = 0; i < 6; i++) - if (cube->xp[i] != i) - return false; - - return true; -} - -bool -check_coud_HTM(Cube *cube) -{ - int i; - - for (i = 0; i < 8; i++) - if (cube->co[i] != 0) - return false; - - return true; -} - -bool -check_coud_URF(Cube *cube) -{ - Cube c2, c3; - - copy_cube(cube, &c2); - copy_cube(cube, &c3); - - apply_move(z, &c2); - apply_move(x, &c3); - - return check_coud_HTM(cube) || - check_coud_HTM(&c2) || - check_coud_HTM(&c3); -} - -bool -check_cp_HTM(Cube *cube) -{ - int i; - - for (i = 0; i < 8; i++) - if (cube->cp[i] != i) - return false; - - return true; -} - -bool -check_corners_HTM(Cube *cube) -{ - return check_coud_HTM(cube) && check_cp_HTM(cube); -} - -bool -check_corners_URF(Cube *cube) -{ - Cube c; - Trans i; - - for (i = 0; i < NROTATIONS; i++) { - copy_cube(cube, &c); - apply_alg(rotation_alg(i), &c); - if (check_corners_HTM(&c)) - return true; - } - - return false; -} - -bool -check_cornershtr(Cube *cube) -{ - /* TODO (use coord) */ - return true; -} - -bool -check_eofb(Cube *cube) -{ - /* TODO (use coord) */ - return true; -} - -bool -check_drud(Cube *cube) -{ - /* TODO (use coord) */ - return true; -} - -bool -check_htr(Cube *cube) -{ - /* TODO (check_drud(cube) and coord_htr_drud == 0) */ - return true; -} - -Alg * -validate_singlecw_ending(Alg *alg) -{ - int i; - bool nor, inv; - Alg *ret; - 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)); - - if (nor && inv) { - ret = new_alg(""); - copy_alg(alg, ret); - } else { - ret = NULL; - } - - return ret; -} - -/* Public functions **********************************************************/ - -/* -void -compute_ind(Step *s, Cube *cube, Movable *ind) -{ - int i; - Cube mvd; - Trans t, tt; - - for (i = 0; i < s->n_coord; i++) { - t = s->coord_trans[i]; - copy_cube(cube, &mvd); - apply_trans(t, &mvd); - - ind[i].val = index_coord(s->coord[i], &mvd, &tt); - ind[i].t = transform_trans(tt, t); - } -} -*/ - -void -prepare_cs(ChoiceStep *cs, SolveOptions *opts) -{ - int i, j; - Step *s; - - for (i = 0; cs->step[i] != NULL; i++) { - s = cs->step[i]; - for (j = 0; j < s->n_coord; j++) { - s->pd[j] = malloc(sizeof(PruneData)); - s->pd[j]->moveset = s->moveset; - s->pd[j]->coord = s->coord[j]; - s->pd[j]->compact = s->pd_compact[j]; - s->pd[j] = genptable(s->pd[j], opts->nthreads); - } - } -} diff --git a/src/steps.h b/src/steps.h @@ -1,243 +0,0 @@ -#ifndef STEPS_H -#define STEPS_H - -#include "pruning.h" -#include "movesets.h" - -bool check_centers(Cube *cube); -bool check_coud_HTM(Cube *cube); -bool check_coud_URF(Cube *cube); -bool check_cp_HTM(Cube *cube); -bool check_corners_HTM(Cube *cube); -bool check_corners_URF(Cube *cube); -bool check_cornershtr(Cube *cube); -bool check_eofb(Cube *cube); -bool check_drud(Cube *cube); -bool check_htr(Cube *cube); -/*void compute_ind(Step *a, Cube *cube, Movable *ind);*/ -void prepare_cs(ChoiceStep *cs, SolveOptions *opts); -bool always_valid(Alg *alg); -Alg * validate_singlecw_ending(Alg *alg); - -#ifndef STEPS_C - -extern char check_centers_msg[100]; -extern char check_eo_msg[100]; -extern char check_dr_msg[100]; -extern char check_htr_msg[100]; -extern char check_drany_msg[100]; - -extern Step step_eofb_HTM; -extern Step step_drud_HTM; -extern Step step_drfin_drud; - -extern ChoiceStep optimal_HTM; -extern ChoiceStep eoany_HTM; -extern ChoiceStep eofb_HTM; -extern ChoiceStep eorl_HTM; -extern ChoiceStep eoud_HTM; -extern ChoiceStep drany_HTM; -extern ChoiceStep drud_HTM; -extern ChoiceStep drrl_HTM; -extern ChoiceStep drfb_HTM; -extern ChoiceStep dranyfin_DR; -extern ChoiceStep drudfin_drud; -extern ChoiceStep drrlfin_drrl; -extern ChoiceStep drfbfin_drfb; - -extern ChoiceStep *csteps[]; - -#else - -char check_centers_msg[100] = "cube must be oriented (centers solved)"; -char check_eo_msg[100] = "EO must be solved on given axis"; -char check_dr_msg[100] = "DR must be solved on given axis"; -char check_htr_msg[100] = "HTR must be solved"; -char check_drany_msg[100] = "DR must be solved on at least one axis"; - -/* Optimal after EO ******************/ -/* TODO: eofin_eo (generic), eofbfin_eofb, eorlfin_eorl, eoudfin_eoud */ - -/* EO steps **************************/ -/* TODO: eoany_HTM (generic), eofb_HTM, eorl_HTM, eoud_HTM */ - -Step -step_eofb_HTM = { - .ready = check_centers, - .final = false, - .moveset = &moveset_HTM, - .n_coord = 1, - .coord = {&coord_eofb}, - .coord_trans = {uf}, - .is_valid = validate_singlecw_ending, -}; -ChoiceStep -eoany_HTM = { - .shortname = "eo", - .name = "EO on any axis", - .step = {&step_eofb_HTM, &step_eofb_HTM, &step_eofb_HTM, NULL}, - .t = {uf, ur, fd}, - .ready_msg = check_centers_msg, -}; -ChoiceStep -eofb_HTM = { - .shortname = "eofb", - .name = "EO on F/B", - .step = {&step_eofb_HTM, NULL}, - .t = {uf}, - .ready_msg = check_centers_msg, -}; -ChoiceStep -eorl_HTM = { - .shortname = "eorl", - .name = "EO on R/L", - .step = {&step_eofb_HTM, NULL}, - .t = {ur}, - .ready_msg = check_centers_msg, -}; -ChoiceStep -eoud_HTM = { - .shortname = "eoud", - .name = "EO on U/D", - .step = {&step_eofb_HTM, NULL}, - .t = {fd}, - .ready_msg = check_centers_msg, -}; - -/* CO steps **************************/ -/* TODO: coany_HTM (generic), cofb_HTM, corl_HTM, coud_HTM */ -/* TODO: coany_URF (generic), cofb_URF, corl_URF, coud_URF */ - -/* Misc corner steps *****************/ -/* TODO: cornershtr_HTM, cornershtr_URF, corners_HTM, corners_URF */ -/* TODO (new): corners_drud */ - -/* DR steps **************************/ -/* TODO: dr_eo (generic) */ -/* TODO: dr_eofb (generic), dr_eorl (generic), dr_eoud (generic) */ -/* TODO: drud_eofb, drrl_eofb, drud_eorl, drfb_eorl, drrl_eoud, drfb_eoud */ - -Step -step_drud_HTM = { - .ready = check_centers, - .final = false, - .moveset = &moveset_HTM, - .n_coord = 1, - .coord = {&coord_drud_sym16}, - .coord_trans = {uf}, - .is_valid = validate_singlecw_ending, -}; -ChoiceStep -drany_HTM = { - .shortname = "dr", - .name = "DR on any axis", - .step = {&step_drud_HTM, &step_drud_HTM, &step_drud_HTM, NULL}, - .t = {uf, rf, fd}, - .ready_msg = check_centers_msg, -}; -ChoiceStep -drud_HTM = { - .shortname = "drud", - .name = "DR on U/D", - .step = {&step_drud_HTM, NULL}, - .t = {uf}, - .ready_msg = check_centers_msg, -}; -ChoiceStep -drrl_HTM = { - .shortname = "drrl", - .name = "DR on R/L", - .step = {&step_drud_HTM, NULL}, - .t = {rf}, - .ready_msg = check_centers_msg, -}; -ChoiceStep -drfb_HTM = { - .shortname = "drfb", - .name = "DR on F/B", - .step = {&step_drud_HTM, NULL}, - .t = {fd}, - .ready_msg = check_centers_msg, -}; - -/* DR finish steps */ -Step -step_drfin_drud = { - .ready = check_drud, - .final = true, - .moveset = &moveset_drud, - .n_coord = 1, - .coord = {&coord_drudfin_noE_sym16}, /* TODO: maybe no noE */ - .coord_trans = {uf}, - .is_valid = NULL, -}; -ChoiceStep -dranyfin_DR = { - .shortname = "drfin", - .name = "DR finish on any axis without breaking DR", - .step = {&step_drfin_drud, &step_drfin_drud, - &step_drfin_drud, NULL}, - .t = {uf, rf, fd}, - .ready_msg = check_dr_msg, -}; -ChoiceStep -drudfin_drud = { - .shortname = "drudfin", - .name = "DR finis on U/D without breaking DR", - .step = {&step_drfin_drud, NULL}, - .t = {uf}, - .ready_msg = check_dr_msg, -}; -ChoiceStep -drrlfin_drrl = { - .shortname = "drrlfin", - .name = "DR finish on R/L without breaking DR", - .step = {&step_drfin_drud, NULL}, - .t = {rf}, - .ready_msg = check_dr_msg, -}; -ChoiceStep -drfbfin_drfb = { - .shortname = "drfbfin", - .name = "DR finish on F/B without breaking DR", - .step = {&step_drfin_drud, NULL}, - .t = {fd}, - .ready_msg = check_dr_msg, -}; - -/* HTR from DR */ -/* TODO: htr_any (generic), htr_drud, htr_drrl, htr_drfb */ - -/* HTR finish */ -/* TODO: htrfin_htr */ - -ChoiceStep *csteps[] = { -/* TODO: this is not a step anymore - &optimal_HTM, -*/ - &eoany_HTM, &eofb_HTM, &eorl_HTM, &eoud_HTM, - &drany_HTM, &drud_HTM, &drrl_HTM, &drfb_HTM, - &dranyfin_DR, &drudfin_drud, &drrlfin_drrl, &drfbfin_drfb, - -NULL -/* TODO: - &optimal_light_HTM, - - &eofin_eo, &eofbfin_eofb, &eorlfin_eorl, &eoudfin_eoud, - &coany_HTM, &coud_HTM, &corl_HTM, &cofb_HTM, - &coany_URF, &coud_URF, &corl_URF, &cofb_URF, - &dr_eo, &dr_eofb, &dr_eorl, &dr_eoud, - &drud_eofb, &drrl_eofb, - &drud_eorl, &drfb_eorl, - &drfb_eoud, &drrl_eoud, - &htr_any, &htr_drud, &htr_drrl, &htr_drfb, - &htrfin_htr, - &cornershtr_HTM, &cornershtr_URF, &corners_HTM, &corners_URF, - NULL -*/ - -}; - -#endif - -#endif diff --git a/www/download/index.html b/www/download/index.html @@ -1,217 +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.3.tar.gz">nissy-2.0.3.tar.gz (67Kb)</a></td> - <td><a href="/nissy-2.0.3.exe">nissy-2.0.3.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.3.tar.gz">2.0.3</a></td> - <td>2022-09-10</td> - <td>Fixed bug in scramble dr</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-3.css b/www/style-3.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; -}