diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2022-09-06 18:00:40 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2022-09-06 18:00:40 +0200 |
| commit | a125e69c8ce0a2764b1e50b2dad0a4fa9d141ef4 (patch) | |
| tree | 71cef86f853f6cae109841cf5bb15bf1b412fdd2 | |
| parent | 072c52f9a54144bc9a58cf2855d5b582f8ba7a1a (diff) | |
| download | nissy-a125e69c8ce0a2764b1e50b2dad0a4fa9d141ef4.tar.gz nissy-a125e69c8ce0a2764b1e50b2dad0a4fa9d141ef4.zip | |
Symcoord version of nissy. Interesting idea, but performance are
actually slower. AT THIS STAGE NISSY IS NOT USABLE.
| -rw-r--r-- | Makefile | 5 | ||||
| -rw-r--r-- | TODO.md | 111 | ||||
| -rw-r--r-- | doc/nissy.1 | 271 | ||||
| -rw-r--r-- | old/maybe-useful-coord.c | 181 | ||||
| -rw-r--r-- | old/maybe-useful-steps.c | 1111 | ||||
| -rw-r--r-- | src/alg.c | 105 | ||||
| -rw-r--r-- | src/alg.h | 76 | ||||
| -rw-r--r-- | src/commands.c | 322 | ||||
| -rw-r--r-- | src/commands.h | 194 | ||||
| -rw-r--r-- | src/coord.c | 976 | ||||
| -rw-r--r-- | src/coord.h | 242 | ||||
| -rw-r--r-- | src/cube.c | 920 | ||||
| -rw-r--r-- | src/cube.h | 44 | ||||
| -rw-r--r-- | src/cubetypes.h | 176 | ||||
| -rw-r--r-- | src/env.c | 2 | ||||
| -rw-r--r-- | src/env.h | 4 | ||||
| -rw-r--r-- | src/moves.c | 409 | ||||
| -rw-r--r-- | src/moves.h | 20 | ||||
| -rw-r--r-- | src/pf.c | 95 | ||||
| -rw-r--r-- | src/pf.h | 20 | ||||
| -rw-r--r-- | src/pruning.c | 265 | ||||
| -rw-r--r-- | src/pruning.h | 21 | ||||
| -rw-r--r-- | src/shell.c | 22 | ||||
| -rw-r--r-- | src/solve.c | 469 | ||||
| -rw-r--r-- | src/solve.h | 4 | ||||
| -rw-r--r-- | src/steps.c | 1514 | ||||
| -rw-r--r-- | src/steps.h | 276 | ||||
| -rw-r--r-- | src/symcoord.c | 687 | ||||
| -rw-r--r-- | src/symcoord.h | 17 | ||||
| -rw-r--r-- | src/trans.c | 381 | ||||
| -rw-r--r-- | src/trans.h | 36 | ||||
| -rw-r--r-- | src/utils.c | 14 | ||||
| -rw-r--r-- | www/download/index.html | 2 | ||||
| -rw-r--r-- | www/examples/index.html | 2 | ||||
| -rw-r--r-- | www/index.html | 2 | ||||
| -rw-r--r-- | www/style-2.css (renamed from www/style.css) | 8 |
36 files changed, 3586 insertions, 5418 deletions
| @@ -1,6 +1,6 @@ | |||
| 1 | # See LICENSE file for copyright and license details. | 1 | # See LICENSE file for copyright and license details. |
| 2 | 2 | ||
| 3 | VERSION = 2.0.2 | 3 | VERSION = post-2.0.2 |
| 4 | 4 | ||
| 5 | PREFIX = /usr/local | 5 | PREFIX = /usr/local |
| 6 | MANPREFIX = ${PREFIX}/share/man | 6 | MANPREFIX = ${PREFIX}/share/man |
| @@ -26,8 +26,7 @@ debug: | |||
| 26 | ${CC} ${DBGFLAGS} -o nissy src/*.c | 26 | ${CC} ${DBGFLAGS} -o nissy src/*.c |
| 27 | 27 | ||
| 28 | clean: | 28 | clean: |
| 29 | rm -rf nissy nissy*.exe nissy*.tar.gz | 29 | rm -rf nissy nissy*.exe nissy*.tar.gz doc/nissy.html doc/nissy.pdf |
| 30 | rm doc/nissy.html doc/nissy.pdf | ||
| 31 | 30 | ||
| 32 | dist: clean nissy.exe | 31 | dist: clean nissy.exe |
| 33 | mkdir -p nissy-${VERSION} | 32 | mkdir -p nissy-${VERSION} |
| @@ -3,50 +3,48 @@ | |||
| 3 | This is a list of things that I would like to add or change at some point. | 3 | This is a list of things that I would like to add or change at some point. |
| 4 | It's more of a personal reminder than anything else. | 4 | It's more of a personal reminder than anything else. |
| 5 | 5 | ||
| 6 | ## Version 2.0.2 | ||
| 7 | ### Website | ||
| 8 | * now gen takes 40 minutes | ||
| 9 | ### Changelog | ||
| 10 | * Only improved table generation speed, but this required huge changes in | ||
| 11 | coordinates.c and symcoord.c (+ some minor changes in other parts). | ||
| 12 | |||
| 13 | ## For version 2.1 | 6 | ## For version 2.1 |
| 14 | ### Coordinates | 7 | ### Slow: it is slower than the old nissy 2.0.2 :( |
| 15 | * Text (README.md) description of coordinate system with 3 (or 4) types of | 8 | * nxopt's trick (switching to reduce branching) actually saves about 50%! |
| 16 | coordinates: basic (+ fundamental), sym, composite (consisting of at most | 9 | * Another factor is estimating *while* moving (i.e. do not move all |
| 17 | one sym + one or more basic) | 10 | coordinates if the first one already gives a high value!) |
| 18 | * Use this to restructure the coordinate part; maybe fundamental coordinates | 11 | * simplify solve, remove everything that is used only by optimal solvers |
| 19 | do not need to exist??? | 12 | * Good compromise: each stepalt offers one of two alternatives: either solve |
| 20 | * Add also "transform" for every coordinate. For example, for EO and similar | 13 | by simply using pruning tables and moving coordinates, or using a custom |
| 21 | only allow transformations that fix the EO axis. | 14 | estimator and moving a cube (or fast_cube) and computing coordinates |
| 22 | * Also: "basic" symcoord do not allow trans, composite coordinates assume | 15 | in the estimator |
| 23 | the transformation fixes the basic sumcoord | 16 | * is there really no way to use inverse branching trick with current system? |
| 24 | * For each coordinate, manually disallow "bad" moves, or just ignore the error | 17 | * new file optimal.c with the old solve logic; try first with the simple |
| 25 | (probably better to check: low performance cost, detect problems that I might | 18 | cube implementation and the new indexers, if it is still slow change |
| 26 | be overlooking) | 19 | to fast_cube (intermediate nissy v2.0.2 implementation) |
| 27 | ### Changes to Step and Solve | 20 | ### Changes to Step and Solve |
| 28 | * Revolutionize: do everything based on coordinates, replace Cube with | 21 | * remove cube from dfsarg? (i still need to save the scramble somewhere, |
| 29 | CubeArray (or just 4 values, so consistency check is super easy); | 22 | but I really only use it in dfs_niss) |
| 30 | remove tables for fast inverse. | 23 | * coord.c: all old coordinates (WIP...) |
| 31 | * No need for most of step data: just solve a list of coordinates | 24 | * steps.c: checkers (use coordinates), all stepalt and steps (WIP...) |
| 32 | (+ associated pruning tables) | 25 | * commands gen and freemem |
| 33 | * For steps that accept multiple solved states (e.g. drany): | 26 | * commands.c: twophase, ...? |
| 34 | just find a way to "merge" multiple steps as alternatives; or | 27 | * Coordinate should have a moveset field? No, at worst there are some garbage |
| 35 | offer multiple lists of coordinates as alternatives | 28 | values in mtable, but no risk for errors |
| 36 | * De Bondt's trick: list of 3 coords (as indexes in coord array of the step) | 29 | ### Rotate, not transform, before solving |
| 37 | that if evaluated to the same pruning value allow for de bondt's trick. | 30 | * solve should re-orient first if needed and not just give up if centers are off |
| 38 | * NISS: compute inverse based on current use moves just before switching, | ||
| 39 | using CubeArray; it is not too slow. | ||
| 40 | ### Loading at startup vs dynamically | ||
| 41 | * Consider moving more things to the initial loading phase (i.e. remove | ||
| 42 | many of the "initialized" parts) | ||
| 43 | ### Documentation | 31 | ### Documentation |
| 32 | * Document how coordinates and pruning tables work now | ||
| 44 | * Write an examples.md file | 33 | * Write an examples.md file |
| 45 | * More screenshots! | 34 | * More screenshots! |
| 46 | ### Tables management | 35 | ### Tables management |
| 47 | * Check files in tables directory, add command to remove old / extraneous files | 36 | * Check files in tables directory automatically remove old / extraneous files |
| 48 | * Add checksum to check that tables are generated / downloaded correctly | 37 | * Add checksum to check that tables are generated / downloaded correctly |
| 49 | * Edit download page update instructions to tell what to do when changing tables | 38 | ### Conditional compiling |
| 39 | * Option to avoid large tables at compile time | ||
| 40 | * option to avoid multithreading (write a simpler solve for t=1, and also | ||
| 41 | check if found enough solutions before checking pruning values) | ||
| 42 | ### Technical | ||
| 43 | * generic option parser | ||
| 44 | * testing? Maybe just hardcode some examples generated with old nissy | ||
| 45 | ### Commands | ||
| 46 | * Easy: add option -I (inverse) and -L (linear, like inverse + normal) | ||
| 47 | to do only linear NISS | ||
| 50 | 48 | ||
| 51 | ## Commands | 49 | ## Commands |
| 52 | 50 | ||
| @@ -62,16 +60,21 @@ including e.g. solutions that were not shown because -c) | |||
| 62 | * 5-side solve (for robots) | 60 | * 5-side solve (for robots) |
| 63 | * Block-building steps (cross, roux blocks, ...) | 61 | * Block-building steps (cross, roux blocks, ...) |
| 64 | * Other common steps (LSE, ...) | 62 | * Other common steps (LSE, ...) |
| 63 | * Larger table for drudfin (include epe)? About 1Gb uncompressed, | ||
| 64 | 500Mb compressed (fallback to noE), 250 compressed + parity trick | ||
| 65 | (is it doable?) | ||
| 65 | 66 | ||
| 66 | ### Improvements to currently implemented commands | 67 | ### Improvements to currently implemented commands |
| 67 | * solve should re-orient first if needed and not just give up if centers are off | 68 | * solve multidfs: do multithread by step, not by alternative (this way |
| 69 | if there are multiple alternatives it can make use of more threads) | ||
| 68 | * solve should try up to a small bound without loading the large pruning table | 70 | * solve should try up to a small bound without loading the large pruning table |
| 71 | (maybe this is not necessary if loading the table is fast enough) | ||
| 69 | * silent batch mode without >>> | 72 | * silent batch mode without >>> |
| 70 | 73 | ||
| 71 | ### New features | 74 | ### New features |
| 75 | * EO analysis (and also DR and HTR analysis): group similar EOs together | ||
| 76 | and such (suggested by Jay) | ||
| 72 | * configurability: add an `alias` command, run config file at startup | 77 | * configurability: add an `alias` command, run config file at startup |
| 73 | * configure max ram to be used (via config file and/or command line option) | ||
| 74 | * transform alg, rufify etc... | ||
| 75 | * command notation to list available moves | 78 | * command notation to list available moves |
| 76 | * make multi-step solve much more general and create command | 79 | * make multi-step solve much more general and create command |
| 77 | * input directly cube status instead of moves | 80 | * input directly cube status instead of moves |
| @@ -105,7 +108,35 @@ including e.g. solutions that were not shown because -c) | |||
| 105 | 108 | ||
| 106 | ### Cleanup | 109 | ### Cleanup |
| 107 | * sort again functions alphabetically in their files | 110 | * sort again functions alphabetically in their files |
| 111 | * change some function and variable names to make everything consistent | ||
| 108 | * more stuff to load at start (or when suitable command is called) rather | 112 | * more stuff to load at start (or when suitable command is called) rather |
| 109 | than when called directly, to avoid nasty problems with threading | 113 | than when called directly, to avoid nasty problems with threading |
| 110 | * parse command args: one function per arg type, then each command has | 114 | * parse command args: one function per arg type, then each command has |
| 111 | a list of options that it accepts (as a string) | 115 | a list of options that it accepts (as a string) |
| 116 | |||
| 117 | ### Style | ||
| 118 | * do not declare all variables at the beginning of a function | ||
| 119 | * remove var names from prototypes | ||
| 120 | * various stuff from style(9) | ||
| 121 | |||
| 122 | ### Random | ||
| 123 | Collect random info like this somewhere: | ||
| 124 | |||
| 125 | Table pt_nxopt31_HTM | ||
| 126 | Base value: 9 | ||
| 127 | 0 1 | ||
| 128 | 1 6 | ||
| 129 | 2 29 | ||
| 130 | 3 164 | ||
| 131 | 4 1433 | ||
| 132 | 5 16772 | ||
| 133 | 6 205033 | ||
| 134 | 7 2513871 | ||
| 135 | 8 30329976 | ||
| 136 | 9 342440769 | ||
| 137 | 10 2815191126 | ||
| 138 | 11 6147967200 | ||
| 139 | 12 524918774 | ||
| 140 | 13 3546 | ||
| 141 | 14 0 | ||
| 142 | 15 0 | ||
diff --git a/doc/nissy.1 b/doc/nissy.1 deleted file mode 100644 index 138d6ae..0000000 --- a/doc/nissy.1 +++ /dev/null | |||
| @@ -1,271 +0,0 @@ | |||
| 1 | .Dd November 2021 | ||
| 2 | .Dt NISSY 1 | ||
| 3 | .Os | ||
| 4 | .Sh NAME | ||
| 5 | .Nm nissy | ||
| 6 | .Nd a Rubik's cube solver and FMC assistant | ||
| 7 | . | ||
| 8 | .Sh SYNOPSIS | ||
| 9 | .Nm | ||
| 10 | .Op Fl b | ||
| 11 | .Nm | ||
| 12 | .Ar command | ||
| 13 | .Op options... | ||
| 14 | . | ||
| 15 | .Sh DESCRIPTION | ||
| 16 | .Nm | ||
| 17 | is a Rubik's Cube solver. | ||
| 18 | It uses techniques from Herbert Kociemba's Cube Explorer and | ||
| 19 | Tomas Rokicki's nxopt. With 4 cores at 2.5GHz and using about 3Gb | ||
| 20 | of RAM, Nissy can find the optimal solution for a random Rubik's cube position | ||
| 21 | in about a minute on average. | ||
| 22 | Nissy can also solve different substeps of the Thistlethwaite's algorithm and more. | ||
| 23 | .Pp | ||
| 24 | When run without any argument an interactive shell is launched, otherwise | ||
| 25 | the provided | ||
| 26 | .Ar command | ||
| 27 | is executed and nissy terminates. If the option | ||
| 28 | .Fl b | ||
| 29 | is given, every argument after it is ignored and the shell is launched without | ||
| 30 | any prompt or welcome message. This can be used to run nissy in batch mode, | ||
| 31 | for example writing a list of commands in a | ||
| 32 | .Ar file | ||
| 33 | (one per line) and running | ||
| 34 | .Ar nissy -b < file | ||
| 35 | .Pp | ||
| 36 | The commands that can be run in the interactive shell are the same that can | ||
| 37 | be run non-interactively and are provided below. | ||
| 38 | . | ||
| 39 | .Sh COMMANDS | ||
| 40 | The available | ||
| 41 | .Ar commands | ||
| 42 | are the following: | ||
| 43 | . | ||
| 44 | .Bl -tag -width Ds | ||
| 45 | . | ||
| 46 | .It Nm cleanup Ar scramble | ||
| 47 | Rewrites the given scramble using only the 18 base (HTM) moves and at most two | ||
| 48 | rotations at the end. If | ||
| 49 | Ar scramble | ||
| 50 | uses NISS, all moves done on normal scramble are written first, followed by | ||
| 51 | all moves done on inverse. | ||
| 52 | . | ||
| 53 | .It Nm commands | ||
| 54 | List all available commands. | ||
| 55 | . | ||
| 56 | .It Nm freemem | ||
| 57 | Release some large tables from memory. You can use this command in case | ||
| 58 | you want to keep nissy open without using too much RAM. | ||
| 59 | . | ||
| 60 | .It Nm gen Op Fl t Ar N | ||
| 61 | Generate all tables used by nissy. Run this to complete your installation. | ||
| 62 | If | ||
| 63 | .Ar N | ||
| 64 | is specified, | ||
| 65 | .Ar N | ||
| 66 | CPU threads will be used (defaults to 64, use less only if you don't want | ||
| 67 | nissy to use all of your CPU resources). | ||
| 68 | . | ||
| 69 | .It Nm help Op Ar command | ||
| 70 | Display help. If no | ||
| 71 | .Ar command | ||
| 72 | is given, a generic help message is printed, otherwise a specific help | ||
| 73 | relative to | ||
| 74 | .Ar command | ||
| 75 | is returned. | ||
| 76 | . | ||
| 77 | .It Nm invert Ar scramble | ||
| 78 | Invert the given scramble. | ||
| 79 | . | ||
| 80 | .It Nm print Ar scramble | ||
| 81 | Display a text-only description of the cube obtained after applying | ||
| 82 | .Ar scramble . | ||
| 83 | . | ||
| 84 | .It Nm quit | ||
| 85 | Quit nissy. | ||
| 86 | . | ||
| 87 | .It Nm scramble Oo Fl n Ar N Oc Oo Ar type Oc | ||
| 88 | Print a randomly-generated (random position) scramble | ||
| 89 | . | ||
| 90 | If | ||
| 91 | .Ar N | ||
| 92 | is given, it produces | ||
| 93 | .Ar N | ||
| 94 | scrambles. | ||
| 95 | .Ar type | ||
| 96 | can be specified to be one of the following: | ||
| 97 | .Bl -tag -width Ds | ||
| 98 | .It Ar corners | ||
| 99 | Scramble with solved edges (only cornes are scrambled). | ||
| 100 | .It Ar dr | ||
| 101 | Scramble with solved DR on U/D. | ||
| 102 | .It Ar edges | ||
| 103 | Scramble with solved corners (only edges are scrambled). | ||
| 104 | .It Ar eo | ||
| 105 | Scramble with solved EO on F/B axis. | ||
| 106 | .It Ar fmc | ||
| 107 | Scramble the full cube and the resulting scramble starts and ends with | ||
| 108 | the moves R\(aq U\(aq F. | ||
| 109 | .It Ar htr | ||
| 110 | Scramble with HTR solved. | ||
| 111 | .El | ||
| 112 | . | ||
| 113 | .It Nm solve Ar step Oo Ar options Oc Ar scramble | ||
| 114 | Solve the given | ||
| 115 | .Ar step | ||
| 116 | on the given | ||
| 117 | .Ar scramble. | ||
| 118 | By default it finds only one (shortest) solution, without using niss, and it | ||
| 119 | displays the number of moves at the end of the line. | ||
| 120 | . | ||
| 121 | The options for the | ||
| 122 | .Ar solve | ||
| 123 | command are the following: | ||
| 124 | . | ||
| 125 | .Bl -tag -width Ds | ||
| 126 | . | ||
| 127 | .It Fl a | ||
| 128 | Print all solutions: some solutions are filtered out by default for some | ||
| 129 | steps, for examples EOs that finish with F\(aq, with this options they are not. | ||
| 130 | . | ||
| 131 | .It Fl c | ||
| 132 | Display only the number of solutions found, not the solutions themselves. | ||
| 133 | . | ||
| 134 | .It Fl m Ar min | ||
| 135 | Only look for solution that are at least | ||
| 136 | .Ar min | ||
| 137 | moves long. | ||
| 138 | . | ||
| 139 | .It Fl M Ar MAX | ||
| 140 | Only look for solution that are at most | ||
| 141 | .Ar MAX | ||
| 142 | moves long. | ||
| 143 | . | ||
| 144 | .It Fl n Ar N | ||
| 145 | Try to find | ||
| 146 | .Ar N | ||
| 147 | solutions. By default and unless the | ||
| 148 | .Fl M | ||
| 149 | or | ||
| 150 | .Fl o | ||
| 151 | options are used, at most one solution is returned. | ||
| 152 | If at least one of | ||
| 153 | .Fl M | ||
| 154 | and | ||
| 155 | .Fl o | ||
| 156 | is used, all the solutions found within the given bounds are returned. | ||
| 157 | The option | ||
| 158 | .Fl s | ||
| 159 | overwrites these default behaviors and at most | ||
| 160 | .Ar N | ||
| 161 | solutions are returned, still satisfiyng the other constraints. | ||
| 162 | . | ||
| 163 | .It Fl N | ||
| 164 | Allow use of NISS. | ||
| 165 | . | ||
| 166 | .It Fl o | ||
| 167 | Only find solutions that require the minimum number of moves. | ||
| 168 | . | ||
| 169 | .It Fl O Ar N | ||
| 170 | Only find solutions that require at most | ||
| 171 | .Ar N | ||
| 172 | moves more than the optimal solution. If | ||
| 173 | .Ar N | ||
| 174 | is 0, this is equivalent to | ||
| 175 | .Fl o | ||
| 176 | . | ||
| 177 | .It Fl p | ||
| 178 | Plain style: do not print the number of moves. | ||
| 179 | . | ||
| 180 | .It Fl t Ar N | ||
| 181 | Use | ||
| 182 | .Ar N | ||
| 183 | CPU threads. By default nissy uses only 1 thread. Using more than one | ||
| 184 | thread will improve performance, but the optimal number depends on your | ||
| 185 | machine and operating system. Generally, using one less than the number | ||
| 186 | of threads of your CPU works quite well. | ||
| 187 | . | ||
| 188 | .It Fl v | ||
| 189 | Verbose mode: print some information during the search and print each solution | ||
| 190 | as it is found instead of only printing them all together at the end. | ||
| 191 | . | ||
| 192 | . | ||
| 193 | .El | ||
| 194 | . | ||
| 195 | .It Nm steps | ||
| 196 | List all available | ||
| 197 | .Ar steps | ||
| 198 | for the | ||
| 199 | .Ar solve | ||
| 200 | command. | ||
| 201 | . | ||
| 202 | .It Nm twophase Ar scramble | ||
| 203 | Find a solution using a two-phase method. This does not guarantee | ||
| 204 | to return an optimal solution (and in fact most often it does not), | ||
| 205 | but it is very fast. | ||
| 206 | . | ||
| 207 | .It Nm unniss Ar scramble | ||
| 208 | Rewrite the scramble without using NISS. | ||
| 209 | . | ||
| 210 | .It Nm version | ||
| 211 | Display version information. | ||
| 212 | . | ||
| 213 | .El | ||
| 214 | . | ||
| 215 | .Sh SCRAMBLES | ||
| 216 | All the commands above that accept a scramble also accept a | ||
| 217 | .Fl Nm i | ||
| 218 | option with no arguments. | ||
| 219 | If this option is given, multiple scrambles are read from standard | ||
| 220 | input (one per line) until and EOF is found, at which point stdin is cleared. | ||
| 221 | . | ||
| 222 | .Sh ENVIRONMENT | ||
| 223 | Data is stored in the folder pointed to by | ||
| 224 | .Nm $NISSYDATA. | ||
| 225 | If that variable is unset the folder | ||
| 226 | .Nm $XDG_DATA_HOME/nissy | ||
| 227 | or | ||
| 228 | .Nm $HOME/.nissy | ||
| 229 | is used instead. If none of this environment variables is defined | ||
| 230 | (e.g. in a non-UNIX system), the current folder is used. | ||
| 231 | . | ||
| 232 | .Sh EXAMPLES | ||
| 233 | .Pp | ||
| 234 | The command: | ||
| 235 | .Dl nissy solve -v -O 1 \(dqR\(aqU\(aqFD2L2FR2U2R2BD2LB2D\(aqB2L\(aqR\(aqBD2BU2LU2R\(aqU\(aqF\(dq | ||
| 236 | Returns: | ||
| 237 | .Dl Searching depth 0 | ||
| 238 | .Dl Searching depth 1 | ||
| 239 | .Dl (some more lines) | ||
| 240 | .Dl Searching depth 16 | ||
| 241 | .Dl D2 F\(aq U2 D2 F\(aq L2 D R2 D F B2 R\(aq L2 F\(aq U\(aq D | ||
| 242 | .Dl Searching depth 17 | ||
| 243 | .Dl D2 F\(aq U2 D2 F\(aq L2 D R2 D F B2 R\(aq L2 F\(aq U\(aq D (16) | ||
| 244 | Notice that the solution is printed twice: the first time it is printed as soon | ||
| 245 | as it is found as requested by the -v option. | ||
| 246 | .Pp | ||
| 247 | The command: | ||
| 248 | .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 | ||
| 249 | Returns: | ||
| 250 | .Dl U B U\(aq B (4) | ||
| 251 | .Dl U (B R\(aq B) (4) | ||
| 252 | .Dl (U B R\(aq B) (4) | ||
| 253 | .Dl U2 F R2 F (4) | ||
| 254 | .Dl U2 B U2 B (4) | ||
| 255 | .Dl (U2 B R\(aq B) (4) | ||
| 256 | .Pp | ||
| 257 | On a UNIX shell, the composite command | ||
| 258 | .Dl nissy scramble -n 2 | nissy solve -i > file.txt | ||
| 259 | Generates two random scrambles, solves them and saves the result to file.txt. | ||
| 260 | The file will look something like this: | ||
| 261 | .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 | ||
| 262 | .Dl U2 R2 F2 L B2 D\(aq R2 D\(aq F U L2 B\(aq U\(aq R2 D2 R2 U (17) | ||
| 263 | .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 | ||
| 264 | .Dl D\(aq F R\(aq D B L2 B R2 L U L U2 B D\(aq U R U F2 (18) | ||
| 265 | . | ||
| 266 | .Sh AUTHORS | ||
| 267 | .An Sebastiano Tronto Aq Mt sebastiano@tronto.net | ||
| 268 | . | ||
| 269 | .Sh SOURCE CODE | ||
| 270 | Source code is available at | ||
| 271 | .Lk https://nissy.tronto.net | ||
diff --git a/old/maybe-useful-coord.c b/old/maybe-useful-coord.c new file mode 100644 index 0000000..9ab2971 --- /dev/null +++ b/old/maybe-useful-coord.c | |||
| @@ -0,0 +1,181 @@ | |||
| 1 | int | ||
| 2 | array_ep_to_epos(int *ep, int *ss) | ||
| 3 | { | ||
| 4 | int epos[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 5 | int eps[4]; | ||
| 6 | int i, j, is; | ||
| 7 | |||
| 8 | for (i = 0, is = 0; i < 12; i++) { | ||
| 9 | for (j = 0; j < 4; j++) { | ||
| 10 | if (ep[i] == ss[j]) { | ||
| 11 | eps[is++] = j; | ||
| 12 | epos[i] = 1; | ||
| 13 | } | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | for (i = 0; i < 4; i++) | ||
| 18 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 19 | |||
| 20 | return 24 * subset_to_index(epos, 12, 4) + perm_to_index(eps, 4); | ||
| 21 | } | ||
| 22 | |||
| 23 | void | ||
| 24 | epos_to_compatible_ep(int epos, int *ep, int *ss) | ||
| 25 | { | ||
| 26 | int i, j, k, other[8]; | ||
| 27 | bool flag; | ||
| 28 | |||
| 29 | for (i = 0; i < 12; i++) | ||
| 30 | ep[i] = -1; | ||
| 31 | |||
| 32 | epos_to_partial_ep(epos, ep, ss); | ||
| 33 | |||
| 34 | for (i = 0, j = 0; i < 12; i++) { | ||
| 35 | flag = false; | ||
| 36 | for (k = 0; k < 4; k++) | ||
| 37 | flag = flag || (i == ss[k]); | ||
| 38 | if (!flag) | ||
| 39 | other[j++] = i; | ||
| 40 | } | ||
| 41 | |||
| 42 | for (i = 0, j = 0; i < 12; i++) | ||
| 43 | if (ep[i] == -1) | ||
| 44 | ep[i] = other[j++]; | ||
| 45 | } | ||
| 46 | |||
| 47 | void | ||
| 48 | epos_to_partial_ep(int epos, int *ep, int *ss) | ||
| 49 | { | ||
| 50 | int i, is, eposs[12], eps[4]; | ||
| 51 | |||
| 52 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 53 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 54 | |||
| 55 | for (i = 0; i < 4; i++) | ||
| 56 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 57 | |||
| 58 | for (i = 0, is = 0; i < 12; i++) | ||
| 59 | if (eposs[i]) | ||
| 60 | ep[i] = ss[eps[is++]]; | ||
| 61 | } | ||
| 62 | |||
| 63 | void | ||
| 64 | fix_eorleoud(CubeArray *arr) | ||
| 65 | { | ||
| 66 | int i; | ||
| 67 | |||
| 68 | for (i = 0; i < 12; i++) { | ||
| 69 | if ((edge_slice(i) == 0 && edge_slice(arr->ep[i]) != 0) || | ||
| 70 | (edge_slice(i) != 0 && edge_slice(arr->ep[i]) == 0)) { | ||
| 71 | arr->eorl[i] = 1 - arr->eofb[i]; | ||
| 72 | } else { | ||
| 73 | arr->eorl[i] = arr->eofb[i]; | ||
| 74 | } | ||
| 75 | |||
| 76 | if ((edge_slice(i) == 2 && edge_slice(arr->ep[i]) != 2) || | ||
| 77 | (edge_slice(i) != 2 && edge_slice(arr->ep[i]) == 2)) { | ||
| 78 | arr->eoud[i] = 1 - arr->eofb[i]; | ||
| 79 | } else { | ||
| 80 | arr->eoud[i] = arr->eofb[i]; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | void | ||
| 86 | fix_cofbcorl(CubeArray *arr) | ||
| 87 | { | ||
| 88 | int i; | ||
| 89 | |||
| 90 | for (i = 0; i < 8; i++) { | ||
| 91 | if (i % 2 == arr->cp[i] % 2) { | ||
| 92 | arr->cofb[i] = arr->coud[i]; | ||
| 93 | arr->corl[i] = arr->coud[i]; | ||
| 94 | } else { | ||
| 95 | if (arr->cp[i] % 2 == 0) { | ||
| 96 | arr->cofb[i] = (arr->coud[i]+1)%3; | ||
| 97 | arr->corl[i] = (arr->coud[i]+2)%3; | ||
| 98 | } else { | ||
| 99 | arr->cofb[i] = (arr->coud[i]+2)%3; | ||
| 100 | arr->corl[i] = (arr->coud[i]+1)%3; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | Cube | ||
| 107 | admissible_ep(Cube cube, PieceFilter f) | ||
| 108 | { | ||
| 109 | CubeArray *arr = new_cubearray(cube, f); | ||
| 110 | Cube ret; | ||
| 111 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 112 | int i, j; | ||
| 113 | |||
| 114 | for (i = 0; i < 12; i++) | ||
| 115 | if (arr->ep[i] != -1) | ||
| 116 | used[arr->ep[i]] = true; | ||
| 117 | |||
| 118 | for (i = 0, j = 0; i < 12; i++) { | ||
| 119 | for ( ; j < 11 && used[j]; j++); | ||
| 120 | if (arr->ep[i] == -1) | ||
| 121 | arr->ep[i] = j++; | ||
| 122 | } | ||
| 123 | |||
| 124 | ret = arrays_to_cube(arr, pf_ep); | ||
| 125 | free_cubearray(arr, f); | ||
| 126 | |||
| 127 | return ret; | ||
| 128 | } | ||
| 129 | |||
| 130 | int | ||
| 131 | edge_slice(Edge e) { | ||
| 132 | if (e < 0 || e > 11) | ||
| 133 | return -1; | ||
| 134 | |||
| 135 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 136 | return 0; | ||
| 137 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 138 | return 1; | ||
| 139 | |||
| 140 | return 2; | ||
| 141 | } | ||
| 142 | |||
| 143 | int | ||
| 144 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 145 | { | ||
| 146 | int arr[12], n, b, x; | ||
| 147 | |||
| 148 | if (!strcmp(orientation, "eofb")) { | ||
| 149 | x = cube.eofb; | ||
| 150 | n = 12; | ||
| 151 | b = 2; | ||
| 152 | } else if (!strcmp(orientation, "eorl")) { | ||
| 153 | x = cube.eorl; | ||
| 154 | n = 12; | ||
| 155 | b = 2; | ||
| 156 | } else if (!strcmp(orientation, "eoud")) { | ||
| 157 | x = cube.eoud; | ||
| 158 | n = 12; | ||
| 159 | b = 2; | ||
| 160 | } else if (!strcmp(orientation, "coud")) { | ||
| 161 | x = cube.coud; | ||
| 162 | n = 8; | ||
| 163 | b = 3; | ||
| 164 | } else if (!strcmp(orientation, "corl")) { | ||
| 165 | x = cube.corl; | ||
| 166 | n = 8; | ||
| 167 | b = 3; | ||
| 168 | } else if (!strcmp(orientation, "cofb")) { | ||
| 169 | x = cube.cofb; | ||
| 170 | n = 8; | ||
| 171 | b = 3; | ||
| 172 | } else { | ||
| 173 | return -1; | ||
| 174 | } | ||
| 175 | |||
| 176 | int_to_sum_zero_array(x, b, n, arr); | ||
| 177 | if (piece < n) | ||
| 178 | return arr[piece]; | ||
| 179 | |||
| 180 | return -1; | ||
| 181 | } | ||
diff --git a/old/maybe-useful-steps.c b/old/maybe-useful-steps.c new file mode 100644 index 0000000..2a20dd9 --- /dev/null +++ b/old/maybe-useful-steps.c | |||
| @@ -0,0 +1,1111 @@ | |||
| 1 | #include "steps.h" | ||
| 2 | |||
| 3 | #define UPDATECHECKSTOP(a, b, c) if ((a=(MAX((a),(b))))>(c)) return (a); | ||
| 4 | |||
| 5 | static int estimate_stepalt(StepAlt *a, uint64_t *ind); | ||
| 6 | |||
| 7 | /* Checkers and validators ***************************************************/ | ||
| 8 | |||
| 9 | /* TODO: these should be with Cube *cube (and all need to change) */ | ||
| 10 | /* Maybe move them to cube.c */ | ||
| 11 | static bool check_centers(Cube cube); | ||
| 12 | static bool check_coud_HTM(Cube cube); | ||
| 13 | static bool check_coud_URF(Cube cube); | ||
| 14 | static bool check_corners_HTM(Cube cube); | ||
| 15 | static bool check_corners_URF(Cube cube); | ||
| 16 | static bool check_cornershtr(Cube cube); | ||
| 17 | static bool check_eofb(Cube cube); | ||
| 18 | static bool check_drud(Cube cube); | ||
| 19 | static bool check_htr(Cube cube); | ||
| 20 | |||
| 21 | static bool always_valid(Alg *alg); | ||
| 22 | static bool validate_singlecw_ending(Alg *alg); | ||
| 23 | |||
| 24 | /* Messages for when cube is not ready ***************************************/ | ||
| 25 | |||
| 26 | static char check_centers_msg[100] = "cube must be oriented (centers solved)"; | ||
| 27 | static char check_eo_msg[100] = "EO must be solved on given axis"; | ||
| 28 | static char check_dr_msg[100] = "DR must be solved on given axis"; | ||
| 29 | static char check_htr_msg[100] = "HTR must be solved"; | ||
| 30 | static char check_drany_msg[100] = "DR must be solved on at least one axis"; | ||
| 31 | |||
| 32 | /* Steps *********************************************************************/ | ||
| 33 | |||
| 34 | /* Optimal solvers *******************/ | ||
| 35 | |||
| 36 | Step | ||
| 37 | optimal_HTM = { | ||
| 38 | .shortname = "optimal", | ||
| 39 | .name = "Optimal solve (in HTM)", | ||
| 40 | |||
| 41 | .final = true, | ||
| 42 | .is_done = is_solved, | ||
| 43 | .estimate = estimate_nxopt31_HTM, | ||
| 44 | .ready = check_centers, | ||
| 45 | .ready_msg = check_centers_msg, | ||
| 46 | .is_valid = always_valid, | ||
| 47 | .moveset = &moveset_HTM, | ||
| 48 | |||
| 49 | .pre_trans = uf, | ||
| 50 | |||
| 51 | .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, | ||
| 52 | .ntables = 2, | ||
| 53 | }; | ||
| 54 | |||
| 55 | Step | ||
| 56 | optimal_light_HTM = { | ||
| 57 | .shortname = "light", | ||
| 58 | .name = "Optimal solve (in HTM), small table (500Mb RAM total)", | ||
| 59 | |||
| 60 | .final = true, | ||
| 61 | .is_done = is_solved, | ||
| 62 | .estimate = estimate_light_HTM, | ||
| 63 | .ready = check_centers, | ||
| 64 | .ready_msg = check_centers_msg, | ||
| 65 | .is_valid = always_valid, | ||
| 66 | .moveset = &moveset_HTM, | ||
| 67 | |||
| 68 | .pre_trans = uf, | ||
| 69 | |||
| 70 | .tables = {&pd_drud_sym16_HTM, &pd_corners_HTM}, | ||
| 71 | .ntables = 2, | ||
| 72 | }; | ||
| 73 | |||
| 74 | /* Optimal after EO ******************/ | ||
| 75 | |||
| 76 | Step | ||
| 77 | eofin_eo = { | ||
| 78 | .shortname = "eofin", | ||
| 79 | .name = "Optimal solve after EO without breaking EO (detected)", | ||
| 80 | |||
| 81 | .final = true, | ||
| 82 | .is_done = is_solved, | ||
| 83 | .estimate = estimate_nxopt31_HTM, | ||
| 84 | .ready = check_eofb, | ||
| 85 | .ready_msg = check_eo_msg, | ||
| 86 | .is_valid = always_valid, | ||
| 87 | .moveset = &moveset_eofb, | ||
| 88 | |||
| 89 | .detect = detect_pretrans_eofb, | ||
| 90 | |||
| 91 | .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, | ||
| 92 | .ntables = 2, | ||
| 93 | }; | ||
| 94 | |||
| 95 | Step | ||
| 96 | eofbfin_eofb = { | ||
| 97 | .shortname = "eofbfin", | ||
| 98 | .name = "Optimal after EO on F/B without breaking EO", | ||
| 99 | |||
| 100 | .final = true, | ||
| 101 | .is_done = is_solved, | ||
| 102 | .estimate = estimate_nxopt31_HTM, | ||
| 103 | .ready = check_eofb, | ||
| 104 | .ready_msg = check_eo_msg, | ||
| 105 | .is_valid = always_valid, | ||
| 106 | .moveset = &moveset_eofb, | ||
| 107 | |||
| 108 | .pre_trans = uf, | ||
| 109 | |||
| 110 | .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, | ||
| 111 | .ntables = 2, | ||
| 112 | }; | ||
| 113 | |||
| 114 | Step | ||
| 115 | eorlfin_eorl = { | ||
| 116 | .shortname = "eorlfin", | ||
| 117 | .name = "Optimal after EO on R/L without breaking EO", | ||
| 118 | |||
| 119 | .final = true, | ||
| 120 | .is_done = is_solved, | ||
| 121 | .estimate = estimate_nxopt31_HTM, | ||
| 122 | .ready = check_eofb, | ||
| 123 | .ready_msg = check_eo_msg, | ||
| 124 | .is_valid = always_valid, | ||
| 125 | .moveset = &moveset_eofb, | ||
| 126 | |||
| 127 | .pre_trans = ur, | ||
| 128 | |||
| 129 | .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, | ||
| 130 | .ntables = 2, | ||
| 131 | }; | ||
| 132 | |||
| 133 | Step | ||
| 134 | eoudfin_eoud = { | ||
| 135 | .shortname = "eoudfin", | ||
| 136 | .name = "Optimal after EO on U/D without breaking EO", | ||
| 137 | |||
| 138 | .final = true, | ||
| 139 | .is_done = is_solved, | ||
| 140 | .estimate = estimate_nxopt31_HTM, | ||
| 141 | .ready = check_eofb, | ||
| 142 | .ready_msg = check_eo_msg, | ||
| 143 | .is_valid = always_valid, | ||
| 144 | .moveset = &moveset_eofb, | ||
| 145 | |||
| 146 | .pre_trans = fd, | ||
| 147 | |||
| 148 | .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, | ||
| 149 | .ntables = 2, | ||
| 150 | }; | ||
| 151 | |||
| 152 | /* EO steps **************************/ | ||
| 153 | Step | ||
| 154 | eoany_HTM = { | ||
| 155 | .shortname = "eo", | ||
| 156 | .name = "EO on any axis", | ||
| 157 | |||
| 158 | .final = false, | ||
| 159 | .is_done = check_eofb, | ||
| 160 | .estimate = estimate_eofb_HTM, | ||
| 161 | .ready = check_centers, | ||
| 162 | .ready_msg = check_centers_msg, | ||
| 163 | .is_valid = validate_singlecw_ending, | ||
| 164 | .moveset = &moveset_HTM, | ||
| 165 | |||
| 166 | .detect = detect_pretrans_void_3axis, | ||
| 167 | |||
| 168 | .tables = {&pd_eofb_HTM}, | ||
| 169 | .ntables = 1, | ||
| 170 | }; | ||
| 171 | |||
| 172 | Step | ||
| 173 | eofb_HTM = { | ||
| 174 | .shortname = "eofb", | ||
| 175 | .name = "EO on F/B", | ||
| 176 | |||
| 177 | .final = false, | ||
| 178 | .is_done = check_eofb, | ||
| 179 | .estimate = estimate_eofb_HTM, | ||
| 180 | .ready = check_centers, | ||
| 181 | .ready_msg = check_centers_msg, | ||
| 182 | .is_valid = validate_singlecw_ending, | ||
| 183 | .moveset = &moveset_HTM, | ||
| 184 | |||
| 185 | .pre_trans = uf, | ||
| 186 | |||
| 187 | .tables = {&pd_eofb_HTM}, | ||
| 188 | .ntables = 1, | ||
| 189 | }; | ||
| 190 | |||
| 191 | Step | ||
| 192 | eorl_HTM = { | ||
| 193 | .shortname = "eorl", | ||
| 194 | .name = "EO on R/L", | ||
| 195 | |||
| 196 | .final = false, | ||
| 197 | .is_done = check_eofb, | ||
| 198 | .estimate = estimate_eofb_HTM, | ||
| 199 | .ready = check_centers, | ||
| 200 | .ready_msg = check_centers_msg, | ||
| 201 | .is_valid = validate_singlecw_ending, | ||
| 202 | .moveset = &moveset_HTM, | ||
| 203 | |||
| 204 | .pre_trans = ur, | ||
| 205 | |||
| 206 | .tables = {&pd_eofb_HTM}, | ||
| 207 | .ntables = 1, | ||
| 208 | }; | ||
| 209 | |||
| 210 | Step | ||
| 211 | eoud_HTM = { | ||
| 212 | .shortname = "eoud", | ||
| 213 | .name = "EO on U/D", | ||
| 214 | |||
| 215 | .final = false, | ||
| 216 | .is_done = check_eofb, | ||
| 217 | .estimate = estimate_eofb_HTM, | ||
| 218 | .ready = check_centers, | ||
| 219 | .ready_msg = check_centers_msg, | ||
| 220 | .is_valid = validate_singlecw_ending, | ||
| 221 | .moveset = &moveset_HTM, | ||
| 222 | |||
| 223 | .pre_trans = fd, | ||
| 224 | |||
| 225 | .tables = {&pd_eofb_HTM}, | ||
| 226 | .ntables = 1, | ||
| 227 | }; | ||
| 228 | |||
| 229 | /* CO steps **************************/ | ||
| 230 | Step | ||
| 231 | coany_HTM = { | ||
| 232 | .shortname = "co", | ||
| 233 | .name = "CO on any axis", | ||
| 234 | |||
| 235 | .final = false, | ||
| 236 | .is_done = check_coud_HTM, | ||
| 237 | .estimate = estimate_coud_HTM, | ||
| 238 | .ready = NULL, | ||
| 239 | .is_valid = validate_singlecw_ending, | ||
| 240 | .moveset = &moveset_HTM, | ||
| 241 | |||
| 242 | .detect = detect_pretrans_void_3axis, | ||
| 243 | |||
| 244 | .tables = {&pd_coud_HTM}, | ||
| 245 | .ntables = 1, | ||
| 246 | }; | ||
| 247 | |||
| 248 | Step | ||
| 249 | coud_HTM = { | ||
| 250 | .shortname = "coud", | ||
| 251 | .name = "CO on U/D", | ||
| 252 | |||
| 253 | .final = false, | ||
| 254 | .is_done = check_coud_HTM, | ||
| 255 | .estimate = estimate_coud_HTM, | ||
| 256 | .ready = NULL, | ||
| 257 | .is_valid = validate_singlecw_ending, | ||
| 258 | .moveset = &moveset_HTM, | ||
| 259 | |||
| 260 | .pre_trans = uf, | ||
| 261 | |||
| 262 | .tables = {&pd_coud_HTM}, | ||
| 263 | .ntables = 1, | ||
| 264 | }; | ||
| 265 | |||
| 266 | Step | ||
| 267 | corl_HTM = { | ||
| 268 | .shortname = "corl", | ||
| 269 | .name = "CO on R/L", | ||
| 270 | |||
| 271 | .final = false, | ||
| 272 | .is_done = check_coud_HTM, | ||
| 273 | .estimate = estimate_coud_HTM, | ||
| 274 | .ready = NULL, | ||
| 275 | .is_valid = validate_singlecw_ending, | ||
| 276 | .moveset = &moveset_HTM, | ||
| 277 | |||
| 278 | .pre_trans = rf, | ||
| 279 | |||
| 280 | .tables = {&pd_coud_HTM}, | ||
| 281 | .ntables = 1, | ||
| 282 | }; | ||
| 283 | |||
| 284 | Step | ||
| 285 | cofb_HTM = { | ||
| 286 | .shortname = "cofb", | ||
| 287 | .name = "CO on F/B", | ||
| 288 | |||
| 289 | .final = false, | ||
| 290 | .is_done = check_coud_HTM, | ||
| 291 | .estimate = estimate_coud_HTM, | ||
| 292 | .ready = NULL, | ||
| 293 | .is_valid = validate_singlecw_ending, | ||
| 294 | .moveset = &moveset_HTM, | ||
| 295 | |||
| 296 | .pre_trans = fd, | ||
| 297 | |||
| 298 | .tables = {&pd_coud_HTM}, | ||
| 299 | .ntables = 1, | ||
| 300 | }; | ||
| 301 | |||
| 302 | Step | ||
| 303 | coany_URF = { | ||
| 304 | .shortname = "co-URF", | ||
| 305 | .name = "CO any axis (URF moveset)", | ||
| 306 | |||
| 307 | .final = false, | ||
| 308 | .is_done = check_coud_URF, | ||
| 309 | .estimate = estimate_coud_URF, | ||
| 310 | .ready = NULL, | ||
| 311 | .is_valid = validate_singlecw_ending, | ||
| 312 | .moveset = &moveset_URF, | ||
| 313 | |||
| 314 | .detect = detect_pretrans_void_3axis, | ||
| 315 | |||
| 316 | .tables = {&pd_coud_HTM}, | ||
| 317 | .ntables = 1, | ||
| 318 | }; | ||
| 319 | |||
| 320 | Step | ||
| 321 | coud_URF = { | ||
| 322 | .shortname = "coud-URF", | ||
| 323 | .name = "CO on U/D (URF moveset)", | ||
| 324 | |||
| 325 | .final = false, | ||
| 326 | .is_done = check_coud_URF, | ||
| 327 | .estimate = estimate_coud_URF, | ||
| 328 | .ready = NULL, | ||
| 329 | .is_valid = validate_singlecw_ending, | ||
| 330 | .moveset = &moveset_URF, | ||
| 331 | |||
| 332 | .pre_trans = uf, | ||
| 333 | |||
| 334 | .tables = {&pd_coud_HTM}, | ||
| 335 | .ntables = 1, | ||
| 336 | }; | ||
| 337 | |||
| 338 | Step | ||
| 339 | corl_URF = { | ||
| 340 | .shortname = "corl-URF", | ||
| 341 | .name = "CO on R/L (URF moveset)", | ||
| 342 | |||
| 343 | .final = false, | ||
| 344 | .is_done = check_coud_URF, | ||
| 345 | .estimate = estimate_coud_URF, | ||
| 346 | .ready = NULL, | ||
| 347 | .is_valid = validate_singlecw_ending, | ||
| 348 | .moveset = &moveset_URF, | ||
| 349 | |||
| 350 | .pre_trans = rf, | ||
| 351 | |||
| 352 | .tables = {&pd_coud_HTM}, | ||
| 353 | .ntables = 1, | ||
| 354 | }; | ||
| 355 | |||
| 356 | Step | ||
| 357 | cofb_URF = { | ||
| 358 | .shortname = "cofb-URF", | ||
| 359 | .name = "CO on F/B (URF moveset)", | ||
| 360 | |||
| 361 | .final = false, | ||
| 362 | .is_done = check_coud_URF, | ||
| 363 | .estimate = estimate_coud_URF, | ||
| 364 | .ready = NULL, | ||
| 365 | .is_valid = validate_singlecw_ending, | ||
| 366 | .moveset = &moveset_URF, | ||
| 367 | |||
| 368 | .pre_trans = fd, | ||
| 369 | |||
| 370 | .tables = {&pd_coud_HTM}, | ||
| 371 | .ntables = 1, | ||
| 372 | }; | ||
| 373 | |||
| 374 | /* Misc corner steps *****************/ | ||
| 375 | Step | ||
| 376 | cornershtr_HTM = { | ||
| 377 | .shortname = "chtr", | ||
| 378 | .name = "Solve corners to HTR state", | ||
| 379 | |||
| 380 | .final = false, | ||
| 381 | .is_done = check_cornershtr, | ||
| 382 | .estimate = estimate_cornershtr_HTM, | ||
| 383 | .ready = NULL, | ||
| 384 | .is_valid = validate_singlecw_ending, | ||
| 385 | .moveset = &moveset_HTM, | ||
| 386 | |||
| 387 | .pre_trans = uf, | ||
| 388 | |||
| 389 | .tables = {&pd_cornershtr_HTM}, | ||
| 390 | .ntables = 1, | ||
| 391 | }; | ||
| 392 | |||
| 393 | Step | ||
| 394 | cornershtr_URF = { | ||
| 395 | .shortname = "chtr-URF", | ||
| 396 | .name = "Solve corners to HTR state (URF moveset)", | ||
| 397 | |||
| 398 | .final = false, | ||
| 399 | .is_done = check_cornershtr, | ||
| 400 | .estimate = estimate_cornershtr_URF, | ||
| 401 | .ready = NULL, | ||
| 402 | .is_valid = validate_singlecw_ending, | ||
| 403 | .moveset = &moveset_URF, | ||
| 404 | |||
| 405 | .pre_trans = uf, | ||
| 406 | |||
| 407 | .tables = {&pd_cornershtr_HTM}, | ||
| 408 | .ntables = 1, | ||
| 409 | }; | ||
| 410 | |||
| 411 | Step | ||
| 412 | corners_HTM = { | ||
| 413 | .shortname = "corners", | ||
| 414 | .name = "Solve corners", | ||
| 415 | |||
| 416 | .final = true, | ||
| 417 | .is_done = check_corners_HTM, | ||
| 418 | .estimate = estimate_corners_HTM, | ||
| 419 | .ready = NULL, | ||
| 420 | .is_valid = always_valid, | ||
| 421 | .moveset = &moveset_HTM, | ||
| 422 | |||
| 423 | .pre_trans = uf, | ||
| 424 | |||
| 425 | .tables = {&pd_corners_HTM}, | ||
| 426 | .ntables = 1, | ||
| 427 | }; | ||
| 428 | |||
| 429 | Step | ||
| 430 | corners_URF = { | ||
| 431 | .shortname = "corners-URF", | ||
| 432 | .name = "Solve corners (URF moveset)", | ||
| 433 | |||
| 434 | .final = true, /* TODO: check if this works with reorient */ | ||
| 435 | .is_done = check_corners_URF, | ||
| 436 | .estimate = estimate_corners_URF, | ||
| 437 | .ready = NULL, | ||
| 438 | .is_valid = always_valid, | ||
| 439 | .moveset = &moveset_URF, | ||
| 440 | |||
| 441 | .pre_trans = uf, | ||
| 442 | |||
| 443 | .tables = {&pd_corners_HTM}, | ||
| 444 | .ntables = 1, | ||
| 445 | }; | ||
| 446 | |||
| 447 | /* DR steps **************************/ | ||
| 448 | Step | ||
| 449 | drany_HTM = { | ||
| 450 | .shortname = "dr", | ||
| 451 | .name = "DR on any axis", | ||
| 452 | |||
| 453 | .final = false, | ||
| 454 | .is_done = check_drud, | ||
| 455 | .estimate = estimate_drud_HTM, | ||
| 456 | .ready = check_centers, | ||
| 457 | .ready_msg = check_centers_msg, | ||
| 458 | .is_valid = validate_singlecw_ending, | ||
| 459 | .moveset = &moveset_HTM, | ||
| 460 | |||
| 461 | .detect = detect_pretrans_void_3axis, | ||
| 462 | |||
| 463 | .tables = {&pd_drud_sym16_HTM}, | ||
| 464 | .ntables = 1, | ||
| 465 | }; | ||
| 466 | |||
| 467 | Step | ||
| 468 | drud_HTM = { | ||
| 469 | .shortname = "drud", | ||
| 470 | .name = "DR on U/D", | ||
| 471 | |||
| 472 | .final = false, | ||
| 473 | .is_done = check_drud, | ||
| 474 | .estimate = estimate_drud_HTM, | ||
| 475 | .ready = check_centers, | ||
| 476 | .ready_msg = check_centers_msg, | ||
| 477 | .is_valid = validate_singlecw_ending, | ||
| 478 | .moveset = &moveset_HTM, | ||
| 479 | |||
| 480 | .pre_trans = uf, | ||
| 481 | |||
| 482 | .tables = {&pd_drud_sym16_HTM}, | ||
| 483 | .ntables = 1, | ||
| 484 | }; | ||
| 485 | |||
| 486 | Step | ||
| 487 | drrl_HTM = { | ||
| 488 | .shortname = "drrl", | ||
| 489 | .name = "DR on R/L", | ||
| 490 | |||
| 491 | .final = false, | ||
| 492 | .is_done = check_drud, | ||
| 493 | .estimate = estimate_drud_HTM, | ||
| 494 | .ready = check_centers, | ||
| 495 | .ready_msg = check_centers_msg, | ||
| 496 | .is_valid = validate_singlecw_ending, | ||
| 497 | .moveset = &moveset_HTM, | ||
| 498 | |||
| 499 | .pre_trans = rf, | ||
| 500 | |||
| 501 | .tables = {&pd_drud_sym16_HTM}, | ||
| 502 | .ntables = 1, | ||
| 503 | }; | ||
| 504 | |||
| 505 | Step | ||
| 506 | drfb_HTM = { | ||
| 507 | .shortname = "drfb", | ||
| 508 | .name = "DR on F/B", | ||
| 509 | |||
| 510 | .final = false, | ||
| 511 | .is_done = check_drud, | ||
| 512 | .estimate = estimate_drud_HTM, | ||
| 513 | .ready = check_centers, | ||
| 514 | .ready_msg = check_centers_msg, | ||
| 515 | .is_valid = validate_singlecw_ending, | ||
| 516 | .moveset = &moveset_HTM, | ||
| 517 | |||
| 518 | .pre_trans = fd, | ||
| 519 | |||
| 520 | .tables = {&pd_drud_sym16_HTM}, | ||
| 521 | .ntables = 1, | ||
| 522 | }; | ||
| 523 | |||
| 524 | /* DR from EO */ | ||
| 525 | Step | ||
| 526 | dr_eo = { | ||
| 527 | .shortname = "dr-eo", | ||
| 528 | .name = "DR without breaking EO (automatically detected)", | ||
| 529 | |||
| 530 | .final = false, | ||
| 531 | .is_done = check_drud, | ||
| 532 | .estimate = estimate_dr_eofb, | ||
| 533 | .ready = check_eofb, | ||
| 534 | .ready_msg = check_eo_msg, | ||
| 535 | .is_valid = validate_singlecw_ending, | ||
| 536 | .moveset = &moveset_eofb, | ||
| 537 | |||
| 538 | .detect = detect_pretrans_eofb, | ||
| 539 | |||
| 540 | .tables = {&pd_drud_eofb}, | ||
| 541 | .ntables = 1, | ||
| 542 | }; | ||
| 543 | |||
| 544 | Step | ||
| 545 | dr_eofb = { | ||
| 546 | .shortname = "dr-eofb", | ||
| 547 | .name = "DR on U/D or R/L without breaking EO on F/B", | ||
| 548 | |||
| 549 | .final = false, | ||
| 550 | .is_done = check_drud, | ||
| 551 | .estimate = estimate_dr_eofb, | ||
| 552 | .ready = check_eofb, | ||
| 553 | .ready_msg = check_eo_msg, | ||
| 554 | .is_valid = validate_singlecw_ending, | ||
| 555 | .moveset = &moveset_eofb, | ||
| 556 | |||
| 557 | .pre_trans = uf, | ||
| 558 | |||
| 559 | .tables = {&pd_drud_eofb}, | ||
| 560 | .ntables = 1, | ||
| 561 | }; | ||
| 562 | |||
| 563 | Step | ||
| 564 | dr_eorl = { | ||
| 565 | .shortname = "dr-eorl", | ||
| 566 | .name = "DR on U/D or F/B without breaking EO on R/L", | ||
| 567 | |||
| 568 | .final = false, | ||
| 569 | .is_done = check_drud, | ||
| 570 | .estimate = estimate_dr_eofb, | ||
| 571 | .ready = check_eofb, | ||
| 572 | .ready_msg = check_eo_msg, | ||
| 573 | .is_valid = validate_singlecw_ending, | ||
| 574 | .moveset = &moveset_eofb, | ||
| 575 | |||
| 576 | .pre_trans = ur, | ||
| 577 | |||
| 578 | .tables = {&pd_drud_eofb}, | ||
| 579 | .ntables = 1, | ||
| 580 | }; | ||
| 581 | |||
| 582 | Step | ||
| 583 | dr_eoud = { | ||
| 584 | .shortname = "dr-eoud", | ||
| 585 | .name = "DR on R/L or F/B without breaking EO on U/D", | ||
| 586 | |||
| 587 | .final = false, | ||
| 588 | .is_done = check_drud, | ||
| 589 | .estimate = estimate_dr_eofb, | ||
| 590 | .ready = check_eofb, | ||
| 591 | .ready_msg = check_eo_msg, | ||
| 592 | .is_valid = validate_singlecw_ending, | ||
| 593 | .moveset = &moveset_eofb, | ||
| 594 | |||
| 595 | .pre_trans = fd, | ||
| 596 | |||
| 597 | .tables = {&pd_drud_eofb}, | ||
| 598 | .ntables = 1, | ||
| 599 | }; | ||
| 600 | |||
| 601 | Step | ||
| 602 | drud_eofb = { | ||
| 603 | .shortname = "drud-eofb", | ||
| 604 | .name = "DR on U/D without breaking EO on F/B", | ||
| 605 | |||
| 606 | .final = false, | ||
| 607 | .is_done = check_drud, | ||
| 608 | .estimate = estimate_drud_eofb, | ||
| 609 | .ready = check_eofb, | ||
| 610 | .ready_msg = check_eo_msg, | ||
| 611 | .is_valid = validate_singlecw_ending, | ||
| 612 | .moveset = &moveset_eofb, | ||
| 613 | |||
| 614 | .pre_trans = uf, | ||
| 615 | |||
| 616 | .tables = {&pd_drud_eofb}, | ||
| 617 | .ntables = 1, | ||
| 618 | }; | ||
| 619 | |||
| 620 | Step | ||
| 621 | drrl_eofb = { | ||
| 622 | .shortname = "drrl-eofb", | ||
| 623 | .name = "DR on R/L without breaking EO on F/B", | ||
| 624 | |||
| 625 | .final = false, | ||
| 626 | .is_done = check_drud, | ||
| 627 | .estimate = estimate_drud_eofb, | ||
| 628 | .ready = check_eofb, | ||
| 629 | .ready_msg = check_eo_msg, | ||
| 630 | .is_valid = validate_singlecw_ending, | ||
| 631 | .moveset = &moveset_eofb, | ||
| 632 | |||
| 633 | .pre_trans = rf, | ||
| 634 | |||
| 635 | .tables = {&pd_drud_eofb}, | ||
| 636 | .ntables = 1, | ||
| 637 | }; | ||
| 638 | |||
| 639 | Step | ||
| 640 | drud_eorl = { | ||
| 641 | .shortname = "drud-eorl", | ||
| 642 | .name = "DR on U/D without breaking EO on R/L", | ||
| 643 | |||
| 644 | .final = false, | ||
| 645 | .is_done = check_drud, | ||
| 646 | .estimate = estimate_drud_eofb, | ||
| 647 | .ready = check_eofb, | ||
| 648 | .ready_msg = check_eo_msg, | ||
| 649 | .is_valid = validate_singlecw_ending, | ||
| 650 | .moveset = &moveset_eofb, | ||
| 651 | |||
| 652 | .pre_trans = ur, | ||
| 653 | |||
| 654 | .tables = {&pd_drud_eofb}, | ||
| 655 | .ntables = 1, | ||
| 656 | }; | ||
| 657 | |||
| 658 | Step | ||
| 659 | drfb_eorl = { | ||
| 660 | .shortname = "drfb-eorl", | ||
| 661 | .name = "DR on F/B without breaking EO on R/L", | ||
| 662 | |||
| 663 | .final = false, | ||
| 664 | .is_done = check_drud, | ||
| 665 | .estimate = estimate_drud_eofb, | ||
| 666 | .ready = check_eofb, | ||
| 667 | .ready_msg = check_eo_msg, | ||
| 668 | .is_valid = validate_singlecw_ending, | ||
| 669 | .moveset = &moveset_eofb, | ||
| 670 | |||
| 671 | .pre_trans = fr, | ||
| 672 | |||
| 673 | .tables = {&pd_drud_eofb}, | ||
| 674 | .ntables = 1, | ||
| 675 | }; | ||
| 676 | |||
| 677 | Step | ||
| 678 | drfb_eoud = { | ||
| 679 | .shortname = "drfb-eoud", | ||
| 680 | .name = "DR on F/B without breaking EO on U/D", | ||
| 681 | |||
| 682 | .final = false, | ||
| 683 | .is_done = check_drud, | ||
| 684 | .estimate = estimate_drud_eofb, | ||
| 685 | .ready = check_eofb, | ||
| 686 | .ready_msg = check_eo_msg, | ||
| 687 | .is_valid = validate_singlecw_ending, | ||
| 688 | .moveset = &moveset_eofb, | ||
| 689 | |||
| 690 | .pre_trans = fd, | ||
| 691 | |||
| 692 | .tables = {&pd_drud_eofb}, | ||
| 693 | .ntables = 1, | ||
| 694 | }; | ||
| 695 | |||
| 696 | Step | ||
| 697 | drrl_eoud = { | ||
| 698 | .shortname = "drrl-eoud", | ||
| 699 | .name = "DR on R/L without breaking EO on U/D", | ||
| 700 | |||
| 701 | .final = false, | ||
| 702 | .is_done = check_drud, | ||
| 703 | .estimate = estimate_drud_eofb, | ||
| 704 | .ready = check_eofb, | ||
| 705 | .ready_msg = check_eo_msg, | ||
| 706 | .is_valid = validate_singlecw_ending, | ||
| 707 | .moveset = &moveset_eofb, | ||
| 708 | |||
| 709 | .pre_trans = rd, | ||
| 710 | |||
| 711 | .tables = {&pd_drud_eofb}, | ||
| 712 | .ntables = 1, | ||
| 713 | }; | ||
| 714 | |||
| 715 | /* DR finish steps */ | ||
| 716 | Step | ||
| 717 | dranyfin_DR = { | ||
| 718 | .shortname = "drfin", | ||
| 719 | .name = "DR finish on any axis without breaking DR", | ||
| 720 | |||
| 721 | .final = true, | ||
| 722 | .is_done = is_solved, | ||
| 723 | .estimate = estimate_drudfin_drud, | ||
| 724 | .ready = check_drud, | ||
| 725 | .ready_msg = check_drany_msg, | ||
| 726 | .is_valid = always_valid, | ||
| 727 | .moveset = &moveset_drud, | ||
| 728 | |||
| 729 | .detect = detect_pretrans_drud, | ||
| 730 | |||
| 731 | .tables = {&pd_drudfin_noE_sym16_drud}, | ||
| 732 | .ntables = 1, | ||
| 733 | }; | ||
| 734 | |||
| 735 | Step | ||
| 736 | drudfin_drud = { | ||
| 737 | .shortname = "drudfin", | ||
| 738 | .name = "DR finish on U/D without breaking DR", | ||
| 739 | |||
| 740 | .final = true, | ||
| 741 | .is_done = is_solved, | ||
| 742 | .estimate = estimate_drudfin_drud, | ||
| 743 | .ready = check_drud, | ||
| 744 | .ready_msg = check_dr_msg, | ||
| 745 | .is_valid = always_valid, | ||
| 746 | .moveset = &moveset_drud, | ||
| 747 | |||
| 748 | .pre_trans = uf, | ||
| 749 | |||
| 750 | .tables = {&pd_drudfin_noE_sym16_drud}, | ||
| 751 | .ntables = 1, | ||
| 752 | }; | ||
| 753 | |||
| 754 | Step | ||
| 755 | drrlfin_drrl = { | ||
| 756 | .shortname = "drrlfin", | ||
| 757 | .name = "DR finish on R/L without breaking DR", | ||
| 758 | |||
| 759 | .final = true, | ||
| 760 | .is_done = is_solved, | ||
| 761 | .estimate = estimate_drudfin_drud, | ||
| 762 | .ready = check_drud, | ||
| 763 | .ready_msg = check_dr_msg, | ||
| 764 | .is_valid = always_valid, | ||
| 765 | .moveset = &moveset_drud, | ||
| 766 | |||
| 767 | .pre_trans = rf, | ||
| 768 | |||
| 769 | .tables = {&pd_drudfin_noE_sym16_drud}, | ||
| 770 | .ntables = 1, | ||
| 771 | }; | ||
| 772 | |||
| 773 | Step | ||
| 774 | drfbfin_drfb = { | ||
| 775 | .shortname = "drfbfin", | ||
| 776 | .name = "DR finish on F/B without breaking DR", | ||
| 777 | |||
| 778 | .final = true, | ||
| 779 | .is_done = is_solved, | ||
| 780 | .estimate = estimate_drudfin_drud, | ||
| 781 | .ready = check_drud, | ||
| 782 | .ready_msg = check_dr_msg, | ||
| 783 | .is_valid = always_valid, | ||
| 784 | .moveset = &moveset_drud, | ||
| 785 | |||
| 786 | .pre_trans = fd, | ||
| 787 | |||
| 788 | .tables = {&pd_drudfin_noE_sym16_drud}, | ||
| 789 | .ntables = 1, | ||
| 790 | }; | ||
| 791 | |||
| 792 | /* HTR from DR */ | ||
| 793 | Step | ||
| 794 | htr_any = { | ||
| 795 | .shortname = "htr", | ||
| 796 | .name = "HTR from DR", | ||
| 797 | |||
| 798 | .final = false, | ||
| 799 | .is_done = check_htr, | ||
| 800 | .estimate = estimate_htr_drud, | ||
| 801 | .ready = check_drud, | ||
| 802 | .ready_msg = check_drany_msg, | ||
| 803 | .is_valid = validate_singlecw_ending, | ||
| 804 | .moveset = &moveset_drud, | ||
| 805 | |||
| 806 | .detect = detect_pretrans_drud, | ||
| 807 | |||
| 808 | .tables = {&pd_htr_drud}, | ||
| 809 | .ntables = 1, | ||
| 810 | }; | ||
| 811 | |||
| 812 | Step | ||
| 813 | htr_drud = { | ||
| 814 | .shortname = "htr-drud", | ||
| 815 | .name = "HTR from DR on U/D", | ||
| 816 | |||
| 817 | .final = false, | ||
| 818 | .is_done = check_htr, | ||
| 819 | .estimate = estimate_htr_drud, | ||
| 820 | .ready = check_drud, | ||
| 821 | .ready_msg = check_dr_msg, | ||
| 822 | .is_valid = validate_singlecw_ending, | ||
| 823 | .moveset = &moveset_drud, | ||
| 824 | |||
| 825 | .pre_trans = uf, | ||
| 826 | |||
| 827 | .tables = {&pd_htr_drud}, | ||
| 828 | .ntables = 1, | ||
| 829 | }; | ||
| 830 | |||
| 831 | Step | ||
| 832 | htr_drrl = { | ||
| 833 | .shortname = "htr-drrl", | ||
| 834 | .name = "HTR from DR on R/L", | ||
| 835 | |||
| 836 | .final = false, | ||
| 837 | .is_done = check_htr, | ||
| 838 | .estimate = estimate_htr_drud, | ||
| 839 | .ready = check_drud, | ||
| 840 | .ready_msg = check_dr_msg, | ||
| 841 | .is_valid = validate_singlecw_ending, | ||
| 842 | .moveset = &moveset_drud, | ||
| 843 | |||
| 844 | .pre_trans = rf, | ||
| 845 | |||
| 846 | .tables = {&pd_htr_drud}, | ||
| 847 | .ntables = 1, | ||
| 848 | }; | ||
| 849 | |||
| 850 | Step | ||
| 851 | htr_drfb = { | ||
| 852 | .shortname = "htr-drfb", | ||
| 853 | .name = "HTR from DR on F/B", | ||
| 854 | |||
| 855 | .final = false, | ||
| 856 | .is_done = check_htr, | ||
| 857 | .estimate = estimate_htr_drud, | ||
| 858 | .ready = check_drud, | ||
| 859 | .ready_msg = check_dr_msg, | ||
| 860 | .is_valid = validate_singlecw_ending, | ||
| 861 | .moveset = &moveset_drud, | ||
| 862 | |||
| 863 | .pre_trans = fd, | ||
| 864 | |||
| 865 | .tables = {&pd_htr_drud}, | ||
| 866 | .ntables = 1, | ||
| 867 | }; | ||
| 868 | |||
| 869 | /* HTR finish */ | ||
| 870 | Step | ||
| 871 | htrfin_htr = { | ||
| 872 | .shortname = "htrfin", | ||
| 873 | .name = "HTR finish without breaking HTR", | ||
| 874 | |||
| 875 | .final = true, | ||
| 876 | .is_done = is_solved, | ||
| 877 | .estimate = estimate_htrfin_htr, | ||
| 878 | .ready = check_htr, | ||
| 879 | .ready_msg = check_htr_msg, | ||
| 880 | .is_valid = always_valid, | ||
| 881 | .moveset = &moveset_htr, | ||
| 882 | |||
| 883 | .pre_trans = uf, | ||
| 884 | |||
| 885 | .tables = {&pd_htrfin_htr}, | ||
| 886 | .ntables = 1, | ||
| 887 | }; | ||
| 888 | |||
| 889 | Step *steps[] = { | ||
| 890 | &optimal_HTM, /* first is default */ | ||
| 891 | &optimal_light_HTM, | ||
| 892 | |||
| 893 | &eofin_eo, | ||
| 894 | &eofbfin_eofb, | ||
| 895 | &eorlfin_eorl, | ||
| 896 | &eoudfin_eoud, | ||
| 897 | |||
| 898 | &eoany_HTM, | ||
| 899 | &eofb_HTM, | ||
| 900 | &eorl_HTM, | ||
| 901 | &eoud_HTM, | ||
| 902 | |||
| 903 | &coany_HTM, | ||
| 904 | &coud_HTM, | ||
| 905 | &corl_HTM, | ||
| 906 | &cofb_HTM, | ||
| 907 | |||
| 908 | &coany_URF, | ||
| 909 | &coud_URF, | ||
| 910 | &corl_URF, | ||
| 911 | &cofb_URF, | ||
| 912 | |||
| 913 | &drany_HTM, | ||
| 914 | &drud_HTM, | ||
| 915 | &drrl_HTM, | ||
| 916 | &drfb_HTM, | ||
| 917 | |||
| 918 | &dr_eo, | ||
| 919 | &dr_eofb, | ||
| 920 | &dr_eorl, | ||
| 921 | &dr_eoud, | ||
| 922 | &drud_eofb, | ||
| 923 | &drrl_eofb, | ||
| 924 | &drud_eorl, | ||
| 925 | &drfb_eorl, | ||
| 926 | &drfb_eoud, | ||
| 927 | &drrl_eoud, | ||
| 928 | |||
| 929 | &dranyfin_DR, | ||
| 930 | &drudfin_drud, | ||
| 931 | &drrlfin_drrl, | ||
| 932 | &drfbfin_drfb, | ||
| 933 | |||
| 934 | &htr_any, | ||
| 935 | &htr_drud, | ||
| 936 | &htr_drrl, | ||
| 937 | &htr_drfb, | ||
| 938 | |||
| 939 | &htrfin_htr, | ||
| 940 | |||
| 941 | &cornershtr_HTM, | ||
| 942 | &cornershtr_URF, | ||
| 943 | &corners_HTM, | ||
| 944 | &corners_URF, | ||
| 945 | |||
| 946 | NULL | ||
| 947 | }; | ||
| 948 | |||
| 949 | /* Checkers and validators ***************************************************/ | ||
| 950 | |||
| 951 | static bool | ||
| 952 | check_centers(Cube cube) | ||
| 953 | { | ||
| 954 | return cube.cpos == 0; | ||
| 955 | } | ||
| 956 | |||
| 957 | static bool | ||
| 958 | check_coud_HTM(Cube cube) | ||
| 959 | { | ||
| 960 | return cube.coud == 0; | ||
| 961 | } | ||
| 962 | |||
| 963 | static bool | ||
| 964 | check_coud_URF(Cube cube) | ||
| 965 | { | ||
| 966 | Cube c2, c3; | ||
| 967 | |||
| 968 | c2 = apply_move(z, cube); | ||
| 969 | c3 = apply_move(x, cube); | ||
| 970 | |||
| 971 | return cube.coud == 0 || c2.coud == 0 || c3.coud == 0; | ||
| 972 | } | ||
| 973 | |||
| 974 | static bool | ||
| 975 | check_corners_URF(Cube cube) | ||
| 976 | { | ||
| 977 | Cube c; | ||
| 978 | Trans i; | ||
| 979 | |||
| 980 | for (i = 0; i < NROTATIONS; i++) { | ||
| 981 | c = apply_alg(rotation_alg(i), cube); | ||
| 982 | if (c.cp && c.coud) | ||
| 983 | return true; | ||
| 984 | } | ||
| 985 | |||
| 986 | return false; | ||
| 987 | } | ||
| 988 | |||
| 989 | static bool | ||
| 990 | check_corners_HTM(Cube cube) | ||
| 991 | { | ||
| 992 | return cube.cp == 0 && cube.coud == 0; | ||
| 993 | } | ||
| 994 | |||
| 995 | static bool | ||
| 996 | check_cornershtr(Cube cube) | ||
| 997 | { | ||
| 998 | return coord_cornershtr.index(cube) == 0; | ||
| 999 | } | ||
| 1000 | |||
| 1001 | static bool | ||
| 1002 | check_eofb(Cube cube) | ||
| 1003 | { | ||
| 1004 | return cube.eofb == 0; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | static bool | ||
| 1008 | check_drud(Cube cube) | ||
| 1009 | { | ||
| 1010 | return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; | ||
| 1011 | } | ||
| 1012 | |||
| 1013 | static bool | ||
| 1014 | check_htr(Cube cube) | ||
| 1015 | { | ||
| 1016 | return check_drud(cube) && coord_htr_drud.index(cube) == 0; | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | static bool | ||
| 1020 | always_valid(Alg *alg) | ||
| 1021 | { | ||
| 1022 | return true; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | static bool | ||
| 1026 | validate_singlecw_ending(Alg *alg) | ||
| 1027 | { | ||
| 1028 | int i; | ||
| 1029 | bool nor, inv; | ||
| 1030 | Move l2 = NULLMOVE, l1 = NULLMOVE, l2i = NULLMOVE, l1i = NULLMOVE; | ||
| 1031 | |||
| 1032 | for (i = 0; i < alg->len; i++) { | ||
| 1033 | if (alg->inv[i]) { | ||
| 1034 | l2i = l1i; | ||
| 1035 | l1i = alg->move[i]; | ||
| 1036 | } else { | ||
| 1037 | l2 = l1; | ||
| 1038 | l1 = alg->move[i]; | ||
| 1039 | } | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | nor = l1 ==base_move(l1) && (!commute(l1, l2) ||l2 ==base_move(l2)); | ||
| 1043 | inv = l1i==base_move(l1i) && (!commute(l1i,l2i)||l2i==base_move(l2i)); | ||
| 1044 | |||
| 1045 | return nor && inv; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | /* Public functions **********************************************************/ | ||
| 1049 | |||
| 1050 | void | ||
| 1051 | compute_ind(StepAlt *a, Cube *cube, uint64_t *ind) | ||
| 1052 | { | ||
| 1053 | |||
| 1054 | } | ||
| 1055 | |||
| 1056 | int | ||
| 1057 | estimate_stepalt(StepAlt *a, uint64_t *ind) | ||
| 1058 | { | ||
| 1059 | int i, ret, est[a->n_coord]; | ||
| 1060 | |||
| 1061 | for (i = 0; i < a->n_coord; i++) { | ||
| 1062 | est[i] = ptableval(a->pd[i], ind[i]); | ||
| 1063 | if (est[i] == 0 && a->compact_pd[i]) | ||
| 1064 | est[i] = ptableval(a->fallback_pd, ind[i] / a->fbmod); | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | for (i = 0; i < a->n_dbtrick; i++) | ||
| 1068 | if (est[a->dbtrick[i][0]] == est[a->dbtrick[i][1]] && | ||
| 1069 | est[a->dbtrick[i][0]] == est[a->dbtrick[i][2]]) | ||
| 1070 | est[a->dbtrick[i][0]] += 1; | ||
| 1071 | |||
| 1072 | for (i = 0, ret = -1; i < a->n_coord; i++) | ||
| 1073 | ret = max(ret, est[i]); | ||
| 1074 | |||
| 1075 | return ret; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | void | ||
| 1079 | prepare_step(Step *step, SolveOptions *opts) | ||
| 1080 | { | ||
| 1081 | int i, j; | ||
| 1082 | PDGenData pdg; | ||
| 1083 | StepAlt *a; | ||
| 1084 | |||
| 1085 | init_moveset(step->moveset); | ||
| 1086 | pdg.moveset = step->moveset; | ||
| 1087 | |||
| 1088 | for (i = 0; step->alt[i] != NULL; i++) { | ||
| 1089 | a = step->alt[i]; | ||
| 1090 | for (j = 0; j < a->n_coord; j++) { | ||
| 1091 | gen_coord(a->coord[j]); | ||
| 1092 | |||
| 1093 | pdg.coord = a->coord[j]; | ||
| 1094 | pdg.compact = a->compact[j]; | ||
| 1095 | pdg.pd = NULL; | ||
| 1096 | |||
| 1097 | a->pd[j] = genptable(&pdg, opts->nthreads); | ||
| 1098 | |||
| 1099 | if (a->compact_pd[j]) { | ||
| 1100 | gen_coord(a->fallback_coord[j]); | ||
| 1101 | |||
| 1102 | pdg.coord = a->fallback_coord[j]; | ||
| 1103 | pdg.compact = false; | ||
| 1104 | pdg.pd = NULL; | ||
| 1105 | |||
| 1106 | a->fallback_pd[j] = | ||
| 1107 | step->genptable(&pdg, opts->nthreads); | ||
| 1108 | } | ||
| 1109 | } | ||
| 1110 | } | ||
| 1111 | } | ||
| @@ -1,68 +1,18 @@ | |||
| 1 | #include "alg.h" | 1 | #define ALG_C |
| 2 | 2 | ||
| 3 | /* Local functions ***********************************************************/ | 3 | #include "alg.h" |
| 4 | 4 | ||
| 5 | static bool allowed_HTM(Move m); | ||
| 6 | static bool allowed_URF(Move m); | ||
| 7 | static bool allowed_eofb(Move m); | ||
| 8 | static bool allowed_drud(Move m); | ||
| 9 | static bool allowed_htr(Move m); | ||
| 10 | static bool allowed_next_HTM(Move l2, Move l1, Move m); | ||
| 11 | static int axis(Move m); | 5 | static int axis(Move m); |
| 12 | |||
| 13 | static void free_alglistnode(AlgListNode *aln); | 6 | static void free_alglistnode(AlgListNode *aln); |
| 14 | static void realloc_alg(Alg *alg, int n); | 7 | static void realloc_alg(Alg *alg, int n); |
| 15 | 8 | ||
| 16 | /* Movesets ******************************************************************/ | 9 | bool |
| 17 | |||
| 18 | Moveset | ||
| 19 | moveset_HTM = { | ||
| 20 | .allowed = allowed_HTM, | ||
| 21 | .allowed_next = allowed_next_HTM, | ||
| 22 | }; | ||
| 23 | |||
| 24 | Moveset | ||
| 25 | moveset_URF = { | ||
| 26 | .allowed = allowed_URF, | ||
| 27 | .allowed_next = allowed_next_HTM, | ||
| 28 | }; | ||
| 29 | |||
| 30 | Moveset | ||
| 31 | moveset_eofb = { | ||
| 32 | .allowed = allowed_eofb, | ||
| 33 | .allowed_next = allowed_next_HTM, | ||
| 34 | }; | ||
| 35 | |||
| 36 | Moveset | ||
| 37 | moveset_drud = { | ||
| 38 | .allowed = allowed_drud, | ||
| 39 | .allowed_next = allowed_next_HTM, | ||
| 40 | }; | ||
| 41 | |||
| 42 | Moveset | ||
| 43 | moveset_htr = { | ||
| 44 | .allowed = allowed_htr, | ||
| 45 | .allowed_next = allowed_next_HTM, | ||
| 46 | }; | ||
| 47 | |||
| 48 | static int nmoveset = 5; | ||
| 49 | static Moveset * all_ms[] = { | ||
| 50 | &moveset_HTM, | ||
| 51 | &moveset_URF, | ||
| 52 | &moveset_eofb, | ||
| 53 | &moveset_drud, | ||
| 54 | &moveset_htr, | ||
| 55 | }; | ||
| 56 | |||
| 57 | /* Functions *****************************************************************/ | ||
| 58 | |||
| 59 | static bool | ||
| 60 | allowed_HTM(Move m) | 10 | allowed_HTM(Move m) |
| 61 | { | 11 | { |
| 62 | return m >= U && m <= B3; | 12 | return m >= U && m <= B3; |
| 63 | } | 13 | } |
| 64 | 14 | ||
| 65 | static bool | 15 | bool |
| 66 | allowed_URF(Move m) | 16 | allowed_URF(Move m) |
| 67 | { | 17 | { |
| 68 | Move b = base_move(m); | 18 | Move b = base_move(m); |
| @@ -70,7 +20,7 @@ allowed_URF(Move m) | |||
| 70 | return b == U || b == R || b == F; | 20 | return b == U || b == R || b == F; |
| 71 | } | 21 | } |
| 72 | 22 | ||
| 73 | static bool | 23 | bool |
| 74 | allowed_eofb(Move m) | 24 | allowed_eofb(Move m) |
| 75 | { | 25 | { |
| 76 | Move b = base_move(m); | 26 | Move b = base_move(m); |
| @@ -79,7 +29,7 @@ allowed_eofb(Move m) | |||
| 79 | ((b == F || b == B) && m == b+1); | 29 | ((b == F || b == B) && m == b+1); |
| 80 | } | 30 | } |
| 81 | 31 | ||
| 82 | static bool | 32 | bool |
| 83 | allowed_drud(Move m) | 33 | allowed_drud(Move m) |
| 84 | { | 34 | { |
| 85 | Move b = base_move(m); | 35 | Move b = base_move(m); |
| @@ -88,7 +38,7 @@ allowed_drud(Move m) | |||
| 88 | ((b == R || b == L || b == F || b == B) && m == b + 1); | 38 | ((b == R || b == L || b == F || b == B) && m == b + 1); |
| 89 | } | 39 | } |
| 90 | 40 | ||
| 91 | static bool | 41 | bool |
| 92 | allowed_htr(Move m) | 42 | allowed_htr(Move m) |
| 93 | { | 43 | { |
| 94 | Move b = base_move(m); | 44 | Move b = base_move(m); |
| @@ -96,8 +46,8 @@ allowed_htr(Move m) | |||
| 96 | return moveset_HTM.allowed(m) && m == b + 1; | 46 | return moveset_HTM.allowed(m) && m == b + 1; |
| 97 | } | 47 | } |
| 98 | 48 | ||
| 99 | static bool | 49 | bool |
| 100 | allowed_next_HTM(Move l2, Move l1, Move m) | 50 | allowed_next_all(Move l2, Move l1, Move m) |
| 101 | { | 51 | { |
| 102 | bool p, q; | 52 | bool p, q; |
| 103 | 53 | ||
| @@ -469,6 +419,34 @@ swapmove(Move *m1, Move *m2) | |||
| 469 | *m2 = aux; | 419 | *m2 = aux; |
| 470 | } | 420 | } |
| 471 | 421 | ||
| 422 | char * | ||
| 423 | trans_string(Trans t) | ||
| 424 | { | ||
| 425 | static char trans_string_aux[NTRANS][20] = { | ||
| 426 | [uf] = "uf", [ur] = "ur", [ub] = "ub", [ul] = "ul", | ||
| 427 | [df] = "df", [dr] = "dr", [db] = "db", [dl] = "dl", | ||
| 428 | [rf] = "rf", [rd] = "rd", [rb] = "rb", [ru] = "ru", | ||
| 429 | [lf] = "lf", [ld] = "ld", [lb] = "lb", [lu] = "lu", | ||
| 430 | [fu] = "fu", [fr] = "fr", [fd] = "fd", [fl] = "fl", | ||
| 431 | [bu] = "bu", [br] = "br", [bd] = "bd", [bl] = "bl", | ||
| 432 | |||
| 433 | [uf_mirror] = "uf*", [ur_mirror] = "ur*", | ||
| 434 | [ub_mirror] = "ub*", [ul_mirror] = "ul*", | ||
| 435 | [df_mirror] = "df*", [dr_mirror] = "dr*", | ||
| 436 | [db_mirror] = "db*", [dl_mirror] = "dl*", | ||
| 437 | [rf_mirror] = "rf*", [rd_mirror] = "rd*", | ||
| 438 | [rb_mirror] = "rb*", [ru_mirror] = "ru*", | ||
| 439 | [lf_mirror] = "lf*", [ld_mirror] = "ld*", | ||
| 440 | [lb_mirror] = "lb*", [lu_mirror] = "lu*", | ||
| 441 | [fu_mirror] = "fu*", [fr_mirror] = "fr*", | ||
| 442 | [fd_mirror] = "fd*", [fl_mirror] = "fl*", | ||
| 443 | [bu_mirror] = "bu*", [br_mirror] = "br*", | ||
| 444 | [bd_mirror] = "bd*", [bl_mirror] = "bl*", | ||
| 445 | }; | ||
| 446 | |||
| 447 | return trans_string_aux[t]; | ||
| 448 | } | ||
| 449 | |||
| 472 | Alg * | 450 | Alg * |
| 473 | unniss(Alg *alg) | 451 | unniss(Alg *alg) |
| 474 | { | 452 | { |
| @@ -513,12 +491,3 @@ init_moveset(Moveset *ms) | |||
| 513 | } | 491 | } |
| 514 | } | 492 | } |
| 515 | } | 493 | } |
| 516 | |||
| 517 | void | ||
| 518 | init_all_movesets() | ||
| 519 | { | ||
| 520 | int i; | ||
| 521 | |||
| 522 | for (i = 0; i < nmoveset; i++) | ||
| 523 | init_moveset(all_ms[i]); | ||
| 524 | } | ||
| @@ -8,12 +8,13 @@ | |||
| 8 | #include "cubetypes.h" | 8 | #include "cubetypes.h" |
| 9 | #include "utils.h" | 9 | #include "utils.h" |
| 10 | 10 | ||
| 11 | extern Moveset moveset_HTM; | 11 | bool allowed_all(Move m); |
| 12 | extern Moveset moveset_URF; | 12 | bool allowed_HTM(Move m); |
| 13 | extern Moveset moveset_eofb; | 13 | bool allowed_URF(Move m); |
| 14 | extern Moveset moveset_drud; | 14 | bool allowed_eofb(Move m); |
| 15 | extern Moveset moveset_htr; | 15 | bool allowed_drud(Move m); |
| 16 | 16 | bool allowed_htr(Move m); | |
| 17 | bool allowed_next_all(Move l2, Move l1, Move m); | ||
| 17 | void append_alg(AlgList *l, Alg *alg); | 18 | void append_alg(AlgList *l, Alg *alg); |
| 18 | void append_move(Alg *alg, Move m, bool inverse); | 19 | void append_move(Alg *alg, Move m, bool inverse); |
| 19 | Move base_move(Move m); | 20 | Move base_move(Move m); |
| @@ -34,10 +35,71 @@ Alg * on_inverse(Alg *alg); | |||
| 34 | void print_alg(Alg *alg, bool l); | 35 | void print_alg(Alg *alg, bool l); |
| 35 | void print_alglist(AlgList *al, bool l); | 36 | void print_alglist(AlgList *al, bool l); |
| 36 | void swapmove(Move *m1, Move *m2); | 37 | void swapmove(Move *m1, Move *m2); |
| 38 | char * trans_string(Trans t); /* Here because similar to move_string, move? */ | ||
| 37 | Alg * unniss(Alg *alg); | 39 | Alg * unniss(Alg *alg); |
| 38 | 40 | ||
| 39 | void init_moveset(Moveset *ms); | 41 | void init_moveset(Moveset *ms); |
| 40 | void init_all_movesets(); | 42 | |
| 43 | /* Movesets ******************************************************************/ | ||
| 44 | |||
| 45 | #ifndef ALG_C | ||
| 46 | |||
| 47 | extern Moveset moveset_HTM; | ||
| 48 | extern Moveset moveset_URF; | ||
| 49 | extern Moveset moveset_eofb; | ||
| 50 | extern Moveset moveset_drud; | ||
| 51 | extern Moveset moveset_htr; | ||
| 52 | |||
| 53 | extern Moveset * all_ms[]; | ||
| 54 | |||
| 55 | #else | ||
| 56 | |||
| 57 | Moveset | ||
| 58 | moveset_HTM = { | ||
| 59 | .name = "HTM", | ||
| 60 | .allowed = allowed_HTM, | ||
| 61 | .allowed_next = allowed_next_all, | ||
| 62 | }; | ||
| 63 | |||
| 64 | Moveset | ||
| 65 | moveset_URF = { | ||
| 66 | .name = "URF", | ||
| 67 | .allowed = allowed_URF, | ||
| 68 | .allowed_next = allowed_next_all, | ||
| 69 | }; | ||
| 70 | |||
| 71 | Moveset | ||
| 72 | moveset_eofb = { | ||
| 73 | .name = "eofb", | ||
| 74 | .allowed = allowed_eofb, | ||
| 75 | .allowed_next = allowed_next_all, | ||
| 76 | }; | ||
| 77 | |||
| 78 | Moveset | ||
| 79 | moveset_drud = { | ||
| 80 | .name = "drud", | ||
| 81 | .allowed = allowed_drud, | ||
| 82 | .allowed_next = allowed_next_all, | ||
| 83 | }; | ||
| 84 | |||
| 85 | Moveset | ||
| 86 | moveset_htr = { | ||
| 87 | .name = "htr", | ||
| 88 | .allowed = allowed_htr, | ||
| 89 | .allowed_next = allowed_next_all, | ||
| 90 | }; | ||
| 91 | |||
| 92 | Moveset * | ||
| 93 | all_ms[] = { | ||
| 94 | &moveset_HTM, | ||
| 95 | &moveset_URF, | ||
| 96 | &moveset_eofb, | ||
| 97 | &moveset_drud, | ||
| 98 | &moveset_htr, | ||
| 99 | NULL | ||
| 100 | }; | ||
| 101 | |||
| 102 | #endif | ||
| 41 | 103 | ||
| 42 | #endif | 104 | #endif |
| 43 | 105 | ||
diff --git a/src/commands.c b/src/commands.c index a91fb4f..7f58ef5 100644 --- a/src/commands.c +++ b/src/commands.c | |||
| @@ -1,187 +1,11 @@ | |||
| 1 | #include "commands.h" | 1 | #define COMMANDS_C |
| 2 | |||
| 3 | /* Arg parsing functions *****************************************************/ | ||
| 4 | |||
| 5 | CommandArgs * gen_parse_args(int c, char **v); | ||
| 6 | CommandArgs * help_parse_args(int c, char **v); | ||
| 7 | CommandArgs * parse_only_scramble(int c, char **v); | ||
| 8 | CommandArgs * parse_no_arg(int c, char **v); | ||
| 9 | CommandArgs * solve_parse_args(int c, char **v); | ||
| 10 | CommandArgs * scramble_parse_args(int c, char **v); | ||
| 11 | |||
| 12 | /* Exec functions ************************************************************/ | ||
| 13 | 2 | ||
| 14 | static void gen_exec(CommandArgs *args); | 3 | #include "commands.h" |
| 15 | static void cleanup_exec(CommandArgs *args); | ||
| 16 | static void invert_exec(CommandArgs *args); | ||
| 17 | static void solve_exec(CommandArgs *args); | ||
| 18 | static void scramble_exec(CommandArgs *args); | ||
| 19 | static void steps_exec(CommandArgs *args); | ||
| 20 | static void commands_exec(CommandArgs *args); | ||
| 21 | static void freemem_exec(CommandArgs *args); | ||
| 22 | static void print_exec(CommandArgs *args); | ||
| 23 | static void twophase_exec(CommandArgs *args); | ||
| 24 | static void help_exec(CommandArgs *args); | ||
| 25 | static void quit_exec(CommandArgs *args); | ||
| 26 | static void unniss_exec(CommandArgs *args); | ||
| 27 | static void version_exec(CommandArgs *args); | ||
| 28 | |||
| 29 | /* Local functions ***********************************************************/ | ||
| 30 | 4 | ||
| 31 | static bool read_step(CommandArgs *args, char *str); | 5 | static bool read_step(CommandArgs *args, char *str); |
| 32 | static bool read_scrtype(CommandArgs *args, char *str); | 6 | static bool read_scrtype(CommandArgs *args, char *str); |
| 33 | static bool read_scramble(int c, char **v, CommandArgs *args); | 7 | static bool read_scramble(int c, char **v, CommandArgs *args); |
| 34 | 8 | ||
| 35 | /* Commands ******************************************************************/ | ||
| 36 | |||
| 37 | Command | ||
| 38 | solve_cmd = { | ||
| 39 | .name = "solve", | ||
| 40 | .usage = "solve STEP [OPTIONS] SCRAMBLE", | ||
| 41 | .description = "Solve a step; see command steps for a list of steps", | ||
| 42 | .parse_args = solve_parse_args, | ||
| 43 | .exec = solve_exec | ||
| 44 | }; | ||
| 45 | |||
| 46 | Command | ||
| 47 | scramble_cmd = { | ||
| 48 | .name = "scramble", | ||
| 49 | .usage = "scramble [TYPE] [-n N]", | ||
| 50 | .description = "Get a random-position scramble", | ||
| 51 | .parse_args = scramble_parse_args, | ||
| 52 | .exec = scramble_exec, | ||
| 53 | }; | ||
| 54 | |||
| 55 | Command | ||
| 56 | gen_cmd = { | ||
| 57 | .name = "gen", | ||
| 58 | .usage = "gen [-t N]", | ||
| 59 | .description = "Generate all tables [using N threads]", | ||
| 60 | .parse_args = gen_parse_args, | ||
| 61 | .exec = gen_exec | ||
| 62 | }; | ||
| 63 | |||
| 64 | Command | ||
| 65 | invert_cmd = { | ||
| 66 | .name = "invert", | ||
| 67 | .usage = "invert SCRAMBLE]", | ||
| 68 | .description = "Invert a scramble", | ||
| 69 | .parse_args = parse_only_scramble, | ||
| 70 | .exec = invert_exec, | ||
| 71 | }; | ||
| 72 | |||
| 73 | Command | ||
| 74 | steps_cmd = { | ||
| 75 | .name = "steps", | ||
| 76 | .usage = "steps", | ||
| 77 | .description = "List available steps", | ||
| 78 | .parse_args = parse_no_arg, | ||
| 79 | .exec = steps_exec | ||
| 80 | }; | ||
| 81 | |||
| 82 | Command | ||
| 83 | commands_cmd = { | ||
| 84 | .name = "commands", | ||
| 85 | .usage = "commands", | ||
| 86 | .description = "List available commands", | ||
| 87 | .parse_args = parse_no_arg, | ||
| 88 | .exec = commands_exec | ||
| 89 | }; | ||
| 90 | |||
| 91 | Command | ||
| 92 | freemem_cmd = { | ||
| 93 | .name = "freemem", | ||
| 94 | .usage = "freemem", | ||
| 95 | .description = "free large tables from RAM", | ||
| 96 | .parse_args = parse_no_arg, | ||
| 97 | .exec = freemem_exec, | ||
| 98 | }; | ||
| 99 | |||
| 100 | Command | ||
| 101 | print_cmd = { | ||
| 102 | .name = "print", | ||
| 103 | .usage = "print SCRAMBLE", | ||
| 104 | .description = "Print written description of the cube", | ||
| 105 | .parse_args = parse_only_scramble, | ||
| 106 | .exec = print_exec, | ||
| 107 | }; | ||
| 108 | |||
| 109 | Command | ||
| 110 | help_cmd = { | ||
| 111 | .name = "help", | ||
| 112 | .usage = "help [COMMAND]", | ||
| 113 | .description = "Display nissy manual page or help on specific command", | ||
| 114 | .parse_args = help_parse_args, | ||
| 115 | .exec = help_exec, | ||
| 116 | }; | ||
| 117 | |||
| 118 | Command | ||
| 119 | twophase_cmd = { | ||
| 120 | .name = "twophase", | ||
| 121 | .usage = "twophase", | ||
| 122 | .description = "Find a solution quickly using a 2-phase method", | ||
| 123 | .parse_args = parse_only_scramble, | ||
| 124 | .exec = twophase_exec, | ||
| 125 | }; | ||
| 126 | |||
| 127 | Command | ||
| 128 | quit_cmd = { | ||
| 129 | .name = "quit", | ||
| 130 | .usage = "quit", | ||
| 131 | .description = "Quit nissy", | ||
| 132 | .parse_args = parse_no_arg, | ||
| 133 | .exec = quit_exec, | ||
| 134 | }; | ||
| 135 | |||
| 136 | Command | ||
| 137 | cleanup_cmd = { | ||
| 138 | .name = "cleanup", | ||
| 139 | .usage = "cleanup SCRAMBLE", | ||
| 140 | .description = "Rewrite a scramble using only standard moves (HTM)", | ||
| 141 | .parse_args = parse_only_scramble, | ||
| 142 | .exec = cleanup_exec, | ||
| 143 | }; | ||
| 144 | |||
| 145 | Command | ||
| 146 | unniss_cmd = { | ||
| 147 | .name = "unniss", | ||
| 148 | .usage = "unniss SCRAMBLE", | ||
| 149 | .description = "Rewrite a scramble without NISS", | ||
| 150 | .parse_args = parse_only_scramble, | ||
| 151 | .exec = unniss_exec, | ||
| 152 | }; | ||
| 153 | |||
| 154 | Command | ||
| 155 | version_cmd = { | ||
| 156 | .name = "version", | ||
| 157 | .usage = "version", | ||
| 158 | .description = "print nissy version", | ||
| 159 | .parse_args = parse_no_arg, | ||
| 160 | .exec = version_exec, | ||
| 161 | }; | ||
| 162 | |||
| 163 | Command *commands[] = { | ||
| 164 | &commands_cmd, | ||
| 165 | &freemem_cmd, | ||
| 166 | &gen_cmd, | ||
| 167 | &help_cmd, | ||
| 168 | &invert_cmd, | ||
| 169 | &print_cmd, | ||
| 170 | &quit_cmd, | ||
| 171 | &solve_cmd, | ||
| 172 | &scramble_cmd, | ||
| 173 | &steps_cmd, | ||
| 174 | &twophase_cmd, | ||
| 175 | &cleanup_cmd, | ||
| 176 | &unniss_cmd, | ||
| 177 | &version_cmd, | ||
| 178 | NULL | ||
| 179 | }; | ||
| 180 | |||
| 181 | /* Other constants ***********************************************************/ | ||
| 182 | |||
| 183 | char *scrtypes[20] = { "eo", "corners", "edges", "fmc", "dr", "htr", NULL }; | ||
| 184 | |||
| 185 | /* Arg parsing functions implementation **************************************/ | 9 | /* Arg parsing functions implementation **************************************/ |
| 186 | 10 | ||
| 187 | CommandArgs * | 11 | CommandArgs * |
| @@ -386,17 +210,15 @@ parse_no_arg(int c, char **v) | |||
| 386 | 210 | ||
| 387 | /* Exec functions implementation *********************************************/ | 211 | /* Exec functions implementation *********************************************/ |
| 388 | 212 | ||
| 389 | static void | 213 | void |
| 390 | solve_exec(CommandArgs *args) | 214 | solve_exec(CommandArgs *args) |
| 391 | { | 215 | { |
| 392 | Cube c; | 216 | Cube c; |
| 393 | AlgList *sols; | 217 | AlgList *sols; |
| 394 | 218 | ||
| 395 | init_all_movesets(); | 219 | make_solved(&c); |
| 396 | init_symcoord(); | 220 | apply_alg(args->scramble, &c); |
| 397 | 221 | sols = solve(&c, args->step, args->opts); | |
| 398 | c = apply_alg(args->scramble, (Cube){0}); | ||
| 399 | sols = solve(c, args->step, args->opts); | ||
| 400 | 222 | ||
| 401 | if (args->opts->count_only) | 223 | if (args->opts->count_only) |
| 402 | printf("%d\n", sols->len); | 224 | printf("%d\n", sols->len); |
| @@ -406,85 +228,64 @@ solve_exec(CommandArgs *args) | |||
| 406 | free_alglist(sols); | 228 | free_alglist(sols); |
| 407 | } | 229 | } |
| 408 | 230 | ||
| 409 | static void | 231 | void |
| 410 | scramble_exec(CommandArgs *args) | 232 | scramble_exec(CommandArgs *args) |
| 411 | { | 233 | { |
| 412 | Cube cube; | 234 | Cube cube; |
| 413 | CubeArray *arr; | ||
| 414 | Alg *scr, *ruf, *aux; | 235 | Alg *scr, *ruf, *aux; |
| 415 | int i, j, eo, ep, co, cp, a[12]; | 236 | int i, j, eo, ep, co, cp; |
| 416 | int eparr[12] = { [8] = 8, [9] = 9, [10] = 10, [11] = 11 }; | ||
| 417 | uint64_t ui, uj, uk; | 237 | uint64_t ui, uj, uk; |
| 418 | 238 | ||
| 419 | init_all_movesets(); | ||
| 420 | init_symcoord(); | ||
| 421 | |||
| 422 | srand(time(NULL)); | 239 | srand(time(NULL)); |
| 423 | 240 | ||
| 424 | for (i = 0; i < args->n; i++) { | 241 | for (i = 0; i < args->n; i++) { |
| 425 | 242 | ||
| 426 | if (!strcmp(args->scrtype, "dr")) { | 243 | if (!strcmp(args->scrtype, "dr")) { |
| 427 | /* Warning: cube is inconsistent because of side CO * | 244 | ui = rand() % FACTORIAL8; |
| 428 | * and EO on U/D. But solve_2phase only solves drfin * | 245 | uj = rand() % FACTORIAL8; |
| 429 | * in this case, so it should be ok. * | 246 | uk = rand() % FACTORIAL4; |
| 430 | * TODO: check this properly * | ||
| 431 | * Moreover we again need to fix parity after * | ||
| 432 | * generating epose manually */ | ||
| 433 | do { | ||
| 434 | ui = rand() % FACTORIAL8; | ||
| 435 | uj = rand() % FACTORIAL8; | ||
| 436 | uk = rand() % FACTORIAL4; | ||
| 437 | |||
| 438 | index_to_perm(ui, 12, a); | ||
| 439 | arr = malloc(sizeof(CubeArray)); | ||
| 440 | arr->ep = eparr; | ||
| 441 | cube = arrays_to_cube(arr, pf_ep); | ||
| 442 | free(arr); | ||
| 443 | 247 | ||
| 444 | cube.cp = uj; | 248 | make_solved(&cube); |
| 445 | cube.epose += uk; | 249 | index_to_perm(ui, 8, cube.cp); |
| 446 | } while (!is_admissible(cube)); | 250 | index_to_perm(uj, 8, cube.ep); |
| 251 | index_to_perm(uk, 4, cube.ep + 8); | ||
| 252 | for (j = 8; j < 12; j++) | ||
| 253 | cube.ep[j] += 8; | ||
| 447 | } else if (!strcmp(args->scrtype, "htr")) { | 254 | } else if (!strcmp(args->scrtype, "htr")) { |
| 448 | /* antindex_htrfin() returns a consistent * | 255 | make_solved(&cube); |
| 449 | * cube, except possibly for parity */ | 256 | /* TODO */ |
| 450 | do { | ||
| 451 | ui = rand() % (24*24/6); | ||
| 452 | cube = (Cube){0}; | ||
| 453 | cube.cp = cornershtrfin_ant[ui]; | ||
| 454 | cube.epose = rand() % 24; | ||
| 455 | cube.eposs = rand() % 24; | ||
| 456 | cube.eposm = rand() % 24; | ||
| 457 | } while (!is_admissible(cube)); | ||
| 458 | } else { | 257 | } else { |
| 459 | eo = rand() % POW2TO11; | ||
| 460 | ep = rand() % FACTORIAL12; | 258 | ep = rand() % FACTORIAL12; |
| 461 | co = rand() % POW3TO7; | ||
| 462 | cp = rand() % FACTORIAL8; | 259 | cp = rand() % FACTORIAL8; |
| 260 | eo = rand() % POW2TO11; | ||
| 261 | co = rand() % POW3TO7; | ||
| 463 | 262 | ||
| 464 | if (!strcmp(args->scrtype, "eo")) { | 263 | if (!strcmp(args->scrtype, "eo")) { |
| 465 | eo = 0; | 264 | eo = 0; |
| 466 | } else if (!strcmp(args->scrtype, "corners")) { | 265 | } else if (!strcmp(args->scrtype, "corners")) { |
| 467 | eo = 0; | 266 | eo = 0; |
| 468 | ep = 0; | 267 | ep = 0; |
| 469 | index_to_perm(cp, 8, a); | ||
| 470 | if (perm_sign(a, 8) == 1) { | ||
| 471 | swap(&a[0], &a[1]); | ||
| 472 | cp = perm_to_index(a, 8); | ||
| 473 | } | ||
| 474 | } else if (!strcmp(args->scrtype, "edges")) { | 268 | } else if (!strcmp(args->scrtype, "edges")) { |
| 475 | co = 0; | 269 | co = 0; |
| 476 | cp = 0; | 270 | cp = 0; |
| 477 | index_to_perm(ep, 12, a); | ||
| 478 | if (perm_sign(a, 12) == 1) { | ||
| 479 | swap(&a[0], &a[1]); | ||
| 480 | ep = perm_to_index(a, 12); | ||
| 481 | } | ||
| 482 | } | 271 | } |
| 483 | cube = fourval_to_cube(eo, ep, co, cp); | 272 | |
| 273 | make_solved(&cube); | ||
| 274 | index_to_perm(ep, 12, cube.ep); | ||
| 275 | index_to_perm(cp, 8, cube.cp); | ||
| 276 | int_to_sum_zero_array(eo, 2, 12, cube.eo); | ||
| 277 | int_to_sum_zero_array(co, 3, 8, cube.co); | ||
| 278 | } | ||
| 279 | |||
| 280 | if (!is_admissible(&cube)) { | ||
| 281 | if (!strcmp(args->scrtype, "corners")) | ||
| 282 | swap(&cube.cp[UFR], &cube.cp[UFL]); | ||
| 283 | else | ||
| 284 | swap(&cube.ep[UF], &cube.ep[UB]); | ||
| 484 | } | 285 | } |
| 485 | 286 | ||
| 486 | /* TODO: can be optimized for htr and dr using htrfin, drfin */ | 287 | /* TODO: can be optimized for htr and dr using htrfin, drfin */ |
| 487 | scr = solve_2phase(cube, 1); | 288 | scr = solve_2phase(&cube, 1); |
| 488 | 289 | ||
| 489 | if (!strcmp(args->scrtype, "fmc")) { | 290 | if (!strcmp(args->scrtype, "fmc")) { |
| 490 | aux = new_alg(""); | 291 | aux = new_alg(""); |
| @@ -513,23 +314,22 @@ scramble_exec(CommandArgs *args) | |||
| 513 | } | 314 | } |
| 514 | } | 315 | } |
| 515 | 316 | ||
| 516 | static void | 317 | void |
| 517 | gen_exec(CommandArgs *args) | 318 | gen_exec(CommandArgs *args) |
| 518 | { | 319 | { |
| 320 | /* TODO: | ||
| 519 | int i; | 321 | int i; |
| 520 | 322 | ||
| 521 | fprintf(stderr, "Generating coordinates...\n"); | 323 | fprintf(stderr, "Generating coordinates...\n"); |
| 522 | init_all_movesets(); | ||
| 523 | init_symcoord(); | ||
| 524 | |||
| 525 | fprintf(stderr, "Generating pruning tables...\n"); | 324 | fprintf(stderr, "Generating pruning tables...\n"); |
| 526 | for (i = 0; all_pd[i] != NULL; i++) | 325 | for (i = 0; all_pd[i] != NULL; i++) |
| 527 | genptable(all_pd[i], args->opts->nthreads); | 326 | genptable(all_pd[i], args->opts->nthreads); |
| 327 | */ | ||
| 528 | 328 | ||
| 529 | fprintf(stderr, "Done!\n"); | 329 | fprintf(stderr, "Done!\n"); |
| 530 | } | 330 | } |
| 531 | 331 | ||
| 532 | static void | 332 | void |
| 533 | invert_exec(CommandArgs *args) | 333 | invert_exec(CommandArgs *args) |
| 534 | { | 334 | { |
| 535 | Alg *inv; | 335 | Alg *inv; |
| @@ -540,7 +340,7 @@ invert_exec(CommandArgs *args) | |||
| 540 | free_alg(inv); | 340 | free_alg(inv); |
| 541 | } | 341 | } |
| 542 | 342 | ||
| 543 | static void | 343 | void |
| 544 | steps_exec(CommandArgs *args) | 344 | steps_exec(CommandArgs *args) |
| 545 | { | 345 | { |
| 546 | int i; | 346 | int i; |
| @@ -549,7 +349,7 @@ steps_exec(CommandArgs *args) | |||
| 549 | printf("%-15s %s\n", steps[i]->shortname, steps[i]->name); | 349 | printf("%-15s %s\n", steps[i]->shortname, steps[i]->name); |
| 550 | } | 350 | } |
| 551 | 351 | ||
| 552 | static void | 352 | void |
| 553 | commands_exec(CommandArgs *args) | 353 | commands_exec(CommandArgs *args) |
| 554 | { | 354 | { |
| 555 | int i; | 355 | int i; |
| @@ -559,9 +359,10 @@ commands_exec(CommandArgs *args) | |||
| 559 | 359 | ||
| 560 | } | 360 | } |
| 561 | 361 | ||
| 562 | static void | 362 | void |
| 563 | freemem_exec(CommandArgs *args) | 363 | freemem_exec(CommandArgs *args) |
| 564 | { | 364 | { |
| 365 | /* TODO: | ||
| 565 | int i; | 366 | int i; |
| 566 | 367 | ||
| 567 | for (i = 0; all_pd[i] != NULL; i++) | 368 | for (i = 0; all_pd[i] != NULL; i++) |
| @@ -569,35 +370,34 @@ freemem_exec(CommandArgs *args) | |||
| 569 | 370 | ||
| 570 | for (i = 0; all_sd[i] != NULL; i++) | 371 | for (i = 0; all_sd[i] != NULL; i++) |
| 571 | free_sd(all_sd[i]); | 372 | free_sd(all_sd[i]); |
| 572 | 373 | */ | |
| 573 | /* TODO: invtables are also large, but for now they are * | ||
| 574 | * statically allocated. Consider releasing those too. */ | ||
| 575 | } | 374 | } |
| 576 | 375 | ||
| 577 | static void | 376 | void |
| 578 | print_exec(CommandArgs *args) | 377 | print_exec(CommandArgs *args) |
| 579 | { | 378 | { |
| 580 | init_moves(); | 379 | Cube c; |
| 581 | print_cube(apply_alg(args->scramble, (Cube){0})); | 380 | |
| 381 | make_solved(&c); | ||
| 382 | apply_alg(args->scramble, &c); | ||
| 383 | print_cube(&c); | ||
| 582 | } | 384 | } |
| 583 | 385 | ||
| 584 | static void | 386 | void |
| 585 | twophase_exec(CommandArgs *args) | 387 | twophase_exec(CommandArgs *args) |
| 586 | { | 388 | { |
| 587 | Cube c; | 389 | Cube c; |
| 588 | Alg *sol; | 390 | Alg *sol; |
| 589 | 391 | ||
| 590 | init_all_movesets(); | 392 | make_solved(&c); |
| 591 | init_symcoord(); | 393 | apply_alg(args->scramble, &c); |
| 592 | 394 | sol = solve_2phase(&c, 1); | |
| 593 | c = apply_alg(args->scramble, (Cube){0}); | ||
| 594 | sol = solve_2phase(c, 1); | ||
| 595 | 395 | ||
| 596 | print_alg(sol, false); | 396 | print_alg(sol, false); |
| 597 | free_alg(sol); | 397 | free_alg(sol); |
| 598 | } | 398 | } |
| 599 | 399 | ||
| 600 | static void | 400 | void |
| 601 | help_exec(CommandArgs *args) | 401 | help_exec(CommandArgs *args) |
| 602 | { | 402 | { |
| 603 | if (args->command == NULL) { | 403 | if (args->command == NULL) { |
| @@ -619,26 +419,24 @@ help_exec(CommandArgs *args) | |||
| 619 | } | 419 | } |
| 620 | } | 420 | } |
| 621 | 421 | ||
| 622 | static void | 422 | void |
| 623 | quit_exec(CommandArgs *args) | 423 | quit_exec(CommandArgs *args) |
| 624 | { | 424 | { |
| 625 | exit(0); | 425 | exit(0); |
| 626 | } | 426 | } |
| 627 | 427 | ||
| 628 | static void | 428 | void |
| 629 | cleanup_exec(CommandArgs *args) | 429 | cleanup_exec(CommandArgs *args) |
| 630 | { | 430 | { |
| 631 | Alg *alg; | 431 | Alg *alg; |
| 632 | 432 | ||
| 633 | init_moves(); | ||
| 634 | |||
| 635 | alg = cleanup(args->scramble); | 433 | alg = cleanup(args->scramble); |
| 636 | print_alg(alg, false); | 434 | print_alg(alg, false); |
| 637 | 435 | ||
| 638 | free_alg(alg); | 436 | free_alg(alg); |
| 639 | } | 437 | } |
| 640 | 438 | ||
| 641 | static void | 439 | void |
| 642 | unniss_exec(CommandArgs *args) | 440 | unniss_exec(CommandArgs *args) |
| 643 | { | 441 | { |
| 644 | Alg *aux; | 442 | Alg *aux; |
| @@ -648,7 +446,7 @@ unniss_exec(CommandArgs *args) | |||
| 648 | free(aux); | 446 | free(aux); |
| 649 | } | 447 | } |
| 650 | 448 | ||
| 651 | static void | 449 | void |
| 652 | version_exec(CommandArgs *args) | 450 | version_exec(CommandArgs *args) |
| 653 | { | 451 | { |
| 654 | printf(VERSION"\n"); | 452 | printf(VERSION"\n"); |
| @@ -691,6 +489,8 @@ static bool | |||
| 691 | read_scrtype(CommandArgs *args, char *str) | 489 | read_scrtype(CommandArgs *args, char *str) |
| 692 | { | 490 | { |
| 693 | int i; | 491 | int i; |
| 492 | static char *scrtypes[20] = | ||
| 493 | { "eo", "corners", "edges", "fmc", "dr", "htr", NULL }; | ||
| 694 | 494 | ||
| 695 | for (i = 0; scrtypes[i] != NULL; i++) { | 495 | for (i = 0; scrtypes[i] != NULL; i++) { |
| 696 | if (!strcmp(scrtypes[i], str)) { | 496 | if (!strcmp(scrtypes[i], str)) { |
diff --git a/src/commands.h b/src/commands.h index b7a4c36..5d9f4ee 100644 --- a/src/commands.h +++ b/src/commands.h | |||
| @@ -9,6 +9,198 @@ | |||
| 9 | void free_args(CommandArgs *args); | 9 | void free_args(CommandArgs *args); |
| 10 | CommandArgs * new_args(); | 10 | CommandArgs * new_args(); |
| 11 | 11 | ||
| 12 | extern Command * commands[]; | 12 | /* Arg parsing functions *****************************************************/ |
| 13 | |||
| 14 | CommandArgs * gen_parse_args(int c, char **v); | ||
| 15 | CommandArgs * help_parse_args(int c, char **v); | ||
| 16 | CommandArgs * parse_only_scramble(int c, char **v); | ||
| 17 | CommandArgs * parse_no_arg(int c, char **v); | ||
| 18 | CommandArgs * solve_parse_args(int c, char **v); | ||
| 19 | CommandArgs * scramble_parse_args(int c, char **v); | ||
| 20 | |||
| 21 | /* Exec functions ************************************************************/ | ||
| 22 | |||
| 23 | void gen_exec(CommandArgs *args); | ||
| 24 | void cleanup_exec(CommandArgs *args); | ||
| 25 | void invert_exec(CommandArgs *args); | ||
| 26 | void solve_exec(CommandArgs *args); | ||
| 27 | void scramble_exec(CommandArgs *args); | ||
| 28 | void steps_exec(CommandArgs *args); | ||
| 29 | void commands_exec(CommandArgs *args); | ||
| 30 | void freemem_exec(CommandArgs *args); | ||
| 31 | void print_exec(CommandArgs *args); | ||
| 32 | void twophase_exec(CommandArgs *args); | ||
| 33 | void help_exec(CommandArgs *args); | ||
| 34 | void quit_exec(CommandArgs *args); | ||
| 35 | void unniss_exec(CommandArgs *args); | ||
| 36 | void version_exec(CommandArgs *args); | ||
| 37 | |||
| 38 | /* Commands ******************************************************************/ | ||
| 39 | |||
| 40 | #ifndef COMMANDS_C | ||
| 41 | |||
| 42 | extern Command cleanup_cmd; | ||
| 43 | extern Command commands_cmd; | ||
| 44 | extern Command freemem_cmd; | ||
| 45 | extern Command gen_cmd; | ||
| 46 | extern Command help_cmd; | ||
| 47 | extern Command invert_cmd; | ||
| 48 | extern Command print_cmd; | ||
| 49 | extern Command quit_cmd; | ||
| 50 | extern Command scramble_cmd; | ||
| 51 | extern Command solve_cmd; | ||
| 52 | extern Command steps_cmd; | ||
| 53 | extern Command unniss_cmd; | ||
| 54 | extern Command version_cmd; | ||
| 55 | |||
| 56 | extern Command *commands[]; | ||
| 57 | |||
| 58 | #else | ||
| 59 | |||
| 60 | Command | ||
| 61 | solve_cmd = { | ||
| 62 | .name = "solve", | ||
| 63 | .usage = "solve STEP [OPTIONS] SCRAMBLE", | ||
| 64 | .description = "Solve a step; see command steps for a list of steps", | ||
| 65 | .parse_args = solve_parse_args, | ||
| 66 | .exec = solve_exec | ||
| 67 | }; | ||
| 68 | |||
| 69 | Command | ||
| 70 | scramble_cmd = { | ||
| 71 | .name = "scramble", | ||
| 72 | .usage = "scramble [TYPE] [-n N]", | ||
| 73 | .description = "Get a random-position scramble", | ||
| 74 | .parse_args = scramble_parse_args, | ||
| 75 | .exec = scramble_exec, | ||
| 76 | }; | ||
| 77 | |||
| 78 | Command | ||
| 79 | gen_cmd = { | ||
| 80 | .name = "gen", | ||
| 81 | .usage = "gen [-t N]", | ||
| 82 | .description = "Generate all tables [using N threads]", | ||
| 83 | .parse_args = gen_parse_args, | ||
| 84 | .exec = gen_exec | ||
| 85 | }; | ||
| 86 | |||
| 87 | Command | ||
| 88 | invert_cmd = { | ||
| 89 | .name = "invert", | ||
| 90 | .usage = "invert SCRAMBLE]", | ||
| 91 | .description = "Invert a scramble", | ||
| 92 | .parse_args = parse_only_scramble, | ||
| 93 | .exec = invert_exec, | ||
| 94 | }; | ||
| 95 | |||
| 96 | Command | ||
| 97 | steps_cmd = { | ||
| 98 | .name = "steps", | ||
| 99 | .usage = "steps", | ||
| 100 | .description = "List available steps", | ||
| 101 | .parse_args = parse_no_arg, | ||
| 102 | .exec = steps_exec | ||
| 103 | }; | ||
| 104 | |||
| 105 | Command | ||
| 106 | commands_cmd = { | ||
| 107 | .name = "commands", | ||
| 108 | .usage = "commands", | ||
| 109 | .description = "List available commands", | ||
| 110 | .parse_args = parse_no_arg, | ||
| 111 | .exec = commands_exec | ||
| 112 | }; | ||
| 113 | |||
| 114 | Command | ||
| 115 | freemem_cmd = { | ||
| 116 | .name = "freemem", | ||
| 117 | .usage = "freemem", | ||
| 118 | .description = "free large tables from RAM", | ||
| 119 | .parse_args = parse_no_arg, | ||
| 120 | .exec = freemem_exec, | ||
| 121 | }; | ||
| 122 | |||
| 123 | Command | ||
| 124 | print_cmd = { | ||
| 125 | .name = "print", | ||
| 126 | .usage = "print SCRAMBLE", | ||
| 127 | .description = "Print written description of the cube", | ||
| 128 | .parse_args = parse_only_scramble, | ||
| 129 | .exec = print_exec, | ||
| 130 | }; | ||
| 131 | |||
| 132 | Command | ||
| 133 | help_cmd = { | ||
| 134 | .name = "help", | ||
| 135 | .usage = "help [COMMAND]", | ||
| 136 | .description = "Display nissy manual page or help on specific command", | ||
| 137 | .parse_args = help_parse_args, | ||
| 138 | .exec = help_exec, | ||
| 139 | }; | ||
| 140 | |||
| 141 | Command | ||
| 142 | twophase_cmd = { | ||
| 143 | .name = "twophase", | ||
| 144 | .usage = "twophase", | ||
| 145 | .description = "Find a solution quickly using a 2-phase method", | ||
| 146 | .parse_args = parse_only_scramble, | ||
| 147 | .exec = twophase_exec, | ||
| 148 | }; | ||
| 149 | |||
| 150 | Command | ||
| 151 | quit_cmd = { | ||
| 152 | .name = "quit", | ||
| 153 | .usage = "quit", | ||
| 154 | .description = "Quit nissy", | ||
| 155 | .parse_args = parse_no_arg, | ||
| 156 | .exec = quit_exec, | ||
| 157 | }; | ||
| 158 | |||
| 159 | Command | ||
| 160 | cleanup_cmd = { | ||
| 161 | .name = "cleanup", | ||
| 162 | .usage = "cleanup SCRAMBLE", | ||
| 163 | .description = "Rewrite a scramble using only standard moves (HTM)", | ||
| 164 | .parse_args = parse_only_scramble, | ||
| 165 | .exec = cleanup_exec, | ||
| 166 | }; | ||
| 167 | |||
| 168 | Command | ||
| 169 | unniss_cmd = { | ||
| 170 | .name = "unniss", | ||
| 171 | .usage = "unniss SCRAMBLE", | ||
| 172 | .description = "Rewrite a scramble without NISS", | ||
| 173 | .parse_args = parse_only_scramble, | ||
| 174 | .exec = unniss_exec, | ||
| 175 | }; | ||
| 176 | |||
| 177 | Command | ||
| 178 | version_cmd = { | ||
| 179 | .name = "version", | ||
| 180 | .usage = "version", | ||
| 181 | .description = "print nissy version", | ||
| 182 | .parse_args = parse_no_arg, | ||
| 183 | .exec = version_exec, | ||
| 184 | }; | ||
| 185 | |||
| 186 | Command *commands[] = { | ||
| 187 | &commands_cmd, | ||
| 188 | &freemem_cmd, | ||
| 189 | &gen_cmd, | ||
| 190 | &help_cmd, | ||
| 191 | &invert_cmd, | ||
| 192 | &print_cmd, | ||
| 193 | &quit_cmd, | ||
| 194 | &solve_cmd, | ||
| 195 | &scramble_cmd, | ||
| 196 | &steps_cmd, | ||
| 197 | &twophase_cmd, | ||
| 198 | &cleanup_cmd, | ||
| 199 | &unniss_cmd, | ||
| 200 | &version_cmd, | ||
| 201 | NULL | ||
| 202 | }; | ||
| 203 | |||
| 204 | #endif | ||
| 13 | 205 | ||
| 14 | #endif | 206 | #endif |
diff --git a/src/coord.c b/src/coord.c index a9df9fd..06f7474 100644 --- a/src/coord.c +++ b/src/coord.c | |||
| @@ -1,611 +1,683 @@ | |||
| 1 | #include "coord.h" | 1 | #define COORD_C |
| 2 | |||
| 3 | static uint64_t index_eofb(Cube cube); | ||
| 4 | static uint64_t index_eofbepos(Cube cube); | ||
| 5 | static uint64_t index_epud(Cube cube); | ||
| 6 | static uint64_t index_coud(Cube cube); | ||
| 7 | static uint64_t index_corners(Cube cube); | ||
| 8 | static uint64_t index_cp(Cube cube); | ||
| 9 | static uint64_t index_cphtr(Cube cube); | ||
| 10 | static uint64_t index_cornershtr(Cube cube); | ||
| 11 | static uint64_t index_cornershtrfin(Cube cube); | ||
| 12 | static uint64_t index_drud(Cube cube); | ||
| 13 | static uint64_t index_drud_eofb(Cube cube); | ||
| 14 | static uint64_t index_htr_drud(Cube cube); | ||
| 15 | static uint64_t index_htrfin(Cube cube); | ||
| 16 | static uint64_t index_cpud_separate(Cube cube); | ||
| 17 | |||
| 18 | static uint64_t move_eofb(Move m, uint64_t ind); | ||
| 19 | static uint64_t move_eofbepos(Move m, uint64_t ind); | ||
| 20 | static uint64_t move_epud(Move m, uint64_t ind); | ||
| 21 | static uint64_t move_coud(Move m, uint64_t ind); | ||
| 22 | static uint64_t move_corners(Move m, uint64_t ind); | ||
| 23 | static uint64_t move_cp(Move m, uint64_t ind); | ||
| 24 | static uint64_t move_cphtr(Move m, uint64_t ind); | ||
| 25 | static uint64_t move_cornershtr(Move m, uint64_t ind); | ||
| 26 | static uint64_t move_cornershtrfin(Move m, uint64_t ind); | ||
| 27 | static uint64_t move_drud(Move m, uint64_t ind); | ||
| 28 | static uint64_t move_drud_eofb(Move m, uint64_t ind); | ||
| 29 | static uint64_t move_htr_drud(Move m, uint64_t ind); | ||
| 30 | static uint64_t move_htrfin(Move m, uint64_t ind); | ||
| 31 | static uint64_t move_cpud_separate(Move m, uint64_t ind); | ||
| 32 | 2 | ||
| 33 | static void init_cphtr_cosets(); | 3 | #include "coord.h" |
| 34 | static void init_cphtr_left_cosets_bfs(int i, int c); | ||
| 35 | static void init_cphtr_right_cosets_color(int i, int c); | ||
| 36 | static void init_cpud_separate(); | ||
| 37 | static void init_cornershtrfin(); | ||
| 38 | static void init_htr_eposs(); | ||
| 39 | 4 | ||
| 5 | static uint64_t indexers_getind(Indexer **is, Cube *c); | ||
| 6 | static uint64_t indexers_getmax(Indexer **is); | ||
| 7 | static void indexers_makecube(Indexer **is, uint64_t ind, Cube *c); | ||
| 8 | static void gen_coord_comp(Coordinate *coord); | ||
| 9 | static void gen_coord_sym(Coordinate *coord); | ||
| 10 | static bool read_coord_mtable(Coordinate *coord); | ||
| 11 | static bool read_coord_sd(Coordinate *coord); | ||
| 12 | static bool read_coord_ttable(Coordinate *coord); | ||
| 13 | static bool write_coord_mtable(Coordinate *coord); | ||
| 14 | static bool write_coord_sd(Coordinate *coord); | ||
| 15 | static bool write_coord_ttable(Coordinate *coord); | ||
| 40 | 16 | ||
| 41 | /* All sorts of useful costants and tables **********************************/ | 17 | /* Indexers ******************************************************************/ |
| 42 | 18 | ||
| 43 | static int cphtr_left_cosets[FACTORIAL8]; | 19 | uint64_t |
| 44 | static int cphtr_right_cosets[FACTORIAL8]; | 20 | index_eofb(Cube *cube) |
| 45 | static int cphtr_right_rep[BINOM8ON4*6]; | 21 | { |
| 46 | int cpud_separate_ind[FACTORIAL8]; | 22 | return (uint64_t)digit_array_to_int(cube->eo, 11, 2); |
| 47 | int cpud_separate_ant[BINOM8ON4]; | 23 | } |
| 48 | static int cornershtrfin_ind[FACTORIAL8]; | ||
| 49 | int cornershtrfin_ant[24*24/6]; | ||
| 50 | static int htr_eposs_ind[BINOM12ON4]; | ||
| 51 | static int htr_eposs_ant[BINOM8ON4]; | ||
| 52 | 24 | ||
| 53 | /* Coordinates and their implementation **************************************/ | 25 | uint64_t |
| 26 | index_coud(Cube *cube) | ||
| 27 | { | ||
| 28 | return (uint64_t)digit_array_to_int(cube->co, 7, 3); | ||
| 29 | } | ||
| 54 | 30 | ||
| 55 | Coordinate | 31 | uint64_t |
| 56 | coord_eofb = { | 32 | index_cp(Cube *cube) |
| 57 | .index = index_eofb, | 33 | { |
| 58 | .max = POW2TO11, | 34 | return (uint64_t)perm_to_index(cube->cp, 8); |
| 59 | .move = move_eofb, | 35 | } |
| 60 | }; | ||
| 61 | 36 | ||
| 62 | Coordinate | 37 | uint64_t |
| 63 | coord_eofbepos = { | 38 | index_cpudsep(Cube *cube) |
| 64 | .index = index_eofbepos, | 39 | { |
| 65 | .max = POW2TO11 * BINOM12ON4, | 40 | int i, c[8]; |
| 66 | .move = move_eofbepos, | ||
| 67 | }; | ||
| 68 | 41 | ||
| 69 | Coordinate | 42 | for (i = 0; i < 8; i++) |
| 70 | coord_coud = { | 43 | c[i] = cube->cp[i] < 4 ? 0 : 1; |
| 71 | .index = index_coud, | ||
| 72 | .max = POW3TO7, | ||
| 73 | .move = move_coud, | ||
| 74 | }; | ||
| 75 | 44 | ||
| 76 | Coordinate | 45 | return (uint64_t)subset_to_index(c, 8, 4); |
| 77 | coord_corners = { | 46 | } |
| 78 | .index = index_corners, | ||
| 79 | .max = POW3TO7 * FACTORIAL8, | ||
| 80 | .move = move_corners, | ||
| 81 | }; | ||
| 82 | 47 | ||
| 83 | Coordinate | 48 | uint64_t |
| 84 | coord_cp = { | 49 | index_epe(Cube *cube) |
| 85 | .index = index_cp, | 50 | { |
| 86 | .max = FACTORIAL8, | 51 | int i, e[4]; |
| 87 | .move = move_cp, | ||
| 88 | }; | ||
| 89 | 52 | ||
| 90 | Coordinate | 53 | for (i = 0; i < 4; i++) |
| 91 | coord_cphtr = { | 54 | e[i] = cube->ep[i+8] - 8; |
| 92 | .index = index_cphtr, | ||
| 93 | .max = BINOM8ON4 * 6, | ||
| 94 | .move = move_cphtr, | ||
| 95 | }; | ||
| 96 | 55 | ||
| 97 | Coordinate | 56 | return (uint64_t)perm_to_index(e, 4); |
| 98 | coord_cornershtr = { | 57 | } |
| 99 | .index = index_cornershtr, | ||
| 100 | .max = POW3TO7 * BINOM8ON4 * 6, | ||
| 101 | .move = move_cornershtr, | ||
| 102 | }; | ||
| 103 | 58 | ||
| 104 | Coordinate | 59 | uint64_t |
| 105 | coord_cornershtrfin = { | 60 | index_epud(Cube *cube) |
| 106 | .index = index_cornershtrfin, | 61 | { |
| 107 | .max = 24*24/6, | 62 | return (uint64_t)perm_to_index(cube->ep, 8); |
| 108 | .move = move_cornershtrfin, | 63 | } |
| 109 | }; | ||
| 110 | 64 | ||
| 111 | Coordinate | 65 | uint64_t |
| 112 | coord_epud = { | 66 | index_epos(Cube *cube) |
| 113 | .index = index_epud, | 67 | { |
| 114 | .max = FACTORIAL8, | 68 | int i, a[12]; |
| 115 | .move = move_epud, | ||
| 116 | }; | ||
| 117 | 69 | ||
| 118 | Coordinate | 70 | for (i = 0; i < 12; i++) |
| 119 | coord_drud = { | 71 | a[i] = (cube->ep[i] < 8) ? 0 : 1; |
| 120 | .index = index_drud, | ||
| 121 | .max = POW2TO11 * POW3TO7 * BINOM12ON4, | ||
| 122 | .move = move_drud, | ||
| 123 | }; | ||
| 124 | 72 | ||
| 125 | Coordinate | 73 | return (uint64_t)subset_to_index(a, 12, 4); |
| 126 | coord_htr_drud = { | 74 | } |
| 127 | .index = index_htr_drud, | ||
| 128 | .max = BINOM8ON4 * 6 * BINOM8ON4, | ||
| 129 | .move = move_htr_drud, | ||
| 130 | }; | ||
| 131 | 75 | ||
| 132 | Coordinate | 76 | uint64_t |
| 133 | coord_htrfin = { | 77 | index_eposepe(Cube *cube) |
| 134 | .index = index_htrfin, | 78 | { |
| 135 | .max = 24 * 24 * 24 *24 * 24 / 6, /* should be /12 but it's ok */ | 79 | int i, j, e[4]; |
| 136 | .move = move_htrfin, | 80 | uint64_t epos, epe; |
| 137 | }; | ||
| 138 | 81 | ||
| 139 | Coordinate | 82 | epos = (uint64_t)index_epos(cube); |
| 140 | coord_drud_eofb = { | 83 | for (i = 0, j = 0; i < 12; i++) |
| 141 | .index = index_drud_eofb, | 84 | if (cube->ep[i] >= 8) |
| 142 | .max = POW3TO7 * BINOM12ON4, | 85 | e[j++] = cube->ep[i] - 8; |
| 143 | .move = move_drud_eofb, | 86 | epe = (uint64_t)perm_to_index(e, 4); |
| 144 | }; | ||
| 145 | 87 | ||
| 146 | Coordinate | 88 | return epos * FACTORIAL4 + epe; |
| 147 | coord_cpud_separate = { | 89 | } |
| 148 | .index = index_cpud_separate, | ||
| 149 | .max = BINOM8ON4, | ||
| 150 | .move = move_cpud_separate, | ||
| 151 | }; | ||
| 152 | 90 | ||
| 153 | /* Indexers ******************************************************************/ | 91 | /* Inverse indexers **********************************************************/ |
| 154 | 92 | ||
| 155 | static uint64_t | 93 | void |
| 156 | index_eofb(Cube cube) | 94 | invindex_eofb(uint64_t ind, Cube *cube) |
| 157 | { | 95 | { |
| 158 | return cube.eofb; | 96 | int_to_sum_zero_array(ind, 2, 12, cube->eo); |
| 159 | } | 97 | } |
| 160 | 98 | ||
| 161 | static uint64_t | 99 | void |
| 162 | index_eofbepos(Cube cube) | 100 | invindex_coud(uint64_t ind, Cube *cube) |
| 163 | { | 101 | { |
| 164 | return (cube.epose / FACTORIAL4) * POW2TO11 + cube.eofb; | 102 | int_to_sum_zero_array(ind, 3, 8, cube->co); |
| 165 | } | 103 | } |
| 166 | 104 | ||
| 167 | static uint64_t | 105 | void |
| 168 | index_epud(Cube cube) | 106 | invindex_cp(uint64_t ind, Cube *cube) |
| 169 | { | 107 | { |
| 170 | uint64_t ret; | 108 | index_to_perm(ind, 8, cube->cp); |
| 171 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 172 | |||
| 173 | ret = perm_to_index(arr->ep, 8); | ||
| 174 | free_cubearray(arr, pf_ep); | ||
| 175 | |||
| 176 | return ret; | ||
| 177 | } | 109 | } |
| 178 | 110 | ||
| 179 | static uint64_t | 111 | void |
| 180 | index_coud(Cube cube) | 112 | invindex_cpudsep(uint64_t ind, Cube *cube) |
| 181 | { | 113 | { |
| 182 | return cube.coud; | 114 | int i, j, k, c[8]; |
| 183 | } | ||
| 184 | 115 | ||
| 185 | static uint64_t | 116 | index_to_subset(ind, 8, 4, c); |
| 186 | index_corners(Cube cube) | 117 | for (i = 0, j = 0, k = 4; i < 8; i++) |
| 187 | { | 118 | cube->cp[i] = c[i] == 0 ? j++ : k++; |
| 188 | return cube.coud * FACTORIAL8 + cube.cp; | ||
| 189 | } | 119 | } |
| 190 | 120 | ||
| 191 | static uint64_t | ||
| 192 | index_cp(Cube cube) | ||
| 193 | { | ||
| 194 | return cube.cp; | ||
| 195 | } | ||
| 196 | 121 | ||
| 197 | static uint64_t | 122 | void |
| 198 | index_cphtr(Cube cube) | 123 | invindex_epe(uint64_t ind, Cube *cube) |
| 199 | { | 124 | { |
| 200 | return cphtr_right_cosets[cube.cp]; | 125 | int i; |
| 126 | |||
| 127 | index_to_perm(ind, 4, &cube->ep[8]); | ||
| 128 | for (i = 0; i < 4; i++) | ||
| 129 | cube->ep[i+8] += 8; | ||
| 201 | } | 130 | } |
| 202 | 131 | ||
| 203 | static uint64_t | 132 | void |
| 204 | index_cornershtr(Cube cube) | 133 | invindex_epud(uint64_t ind, Cube *cube) |
| 205 | { | 134 | { |
| 206 | return cube.coud * BINOM8ON4 * 6 + index_cphtr(cube); | 135 | index_to_perm(ind, 8, cube->ep); |
| 207 | } | 136 | } |
| 208 | 137 | ||
| 209 | static uint64_t | 138 | void |
| 210 | index_cornershtrfin(Cube cube) | 139 | invindex_epos(uint64_t ind, Cube *cube) |
| 211 | { | 140 | { |
| 212 | return cornershtrfin_ind[cube.cp]; | 141 | int i, j, k; |
| 142 | |||
| 143 | index_to_subset(ind, 12, 4, cube->ep); | ||
| 144 | for (i = 0, j = 0, k = 8; i < 12; i++) | ||
| 145 | if (cube->ep[i] == 0) | ||
| 146 | cube->ep[i] = j++; | ||
| 147 | else | ||
| 148 | cube->ep[i] = k++; | ||
| 213 | } | 149 | } |
| 214 | 150 | ||
| 215 | static uint64_t | 151 | void |
| 216 | index_drud(Cube cube) | 152 | invindex_eposepe(uint64_t ind, Cube *cube) |
| 217 | { | 153 | { |
| 218 | uint64_t a, b, c; | 154 | int i, j, k, e[4]; |
| 155 | uint64_t epos, epe; | ||
| 219 | 156 | ||
| 220 | a = cube.eofb; | 157 | epos = ind / FACTORIAL4; |
| 221 | b = cube.coud; | 158 | epe = ind % FACTORIAL4; |
| 222 | c = cube.epose / FACTORIAL4; | ||
| 223 | 159 | ||
| 224 | b *= POW2TO11; | 160 | index_to_subset(epos, 12, 4, cube->ep); |
| 225 | c *= POW2TO11 * POW3TO7; | 161 | index_to_perm(epe, 4, e); |
| 226 | 162 | ||
| 227 | return a + b + c; | 163 | for (i = 0, j = 0, k = 0; i < 12; i++) |
| 164 | if (cube->ep[i] == 0) | ||
| 165 | cube->ep[i] = j++; | ||
| 166 | else | ||
| 167 | cube->ep[i] = e[k++] + 8; | ||
| 228 | } | 168 | } |
| 229 | 169 | ||
| 230 | static uint64_t | 170 | /* Other local functions *****************************************************/ |
| 231 | index_drud_eofb(Cube cube) | ||
| 232 | { | ||
| 233 | return index_drud(cube) / POW2TO11; | ||
| 234 | } | ||
| 235 | 171 | ||
| 236 | static uint64_t | 172 | static uint64_t |
| 237 | index_htr_drud(Cube cube) | 173 | indexers_getmax(Indexer **is) |
| 238 | { | 174 | { |
| 239 | uint64_t a, b; | 175 | int i; |
| 176 | uint64_t max = 1; | ||
| 240 | 177 | ||
| 241 | a = index_cphtr(cube); | 178 | for (i = 0; is[i] != NULL; i++) |
| 242 | b = htr_eposs_ind[cube.eposs/24]; | 179 | max *= is[i]->n; |
| 243 | 180 | ||
| 244 | return a * BINOM8ON4 + b; | 181 | return max; |
| 245 | } | 182 | } |
| 246 | 183 | ||
| 247 | static uint64_t | 184 | static uint64_t |
| 248 | index_htrfin(Cube cube) | 185 | indexers_getind(Indexer **is, Cube *c) |
| 249 | { | 186 | { |
| 250 | uint64_t epe, eps, epm, cp, ep; | 187 | int i; |
| 188 | uint64_t max = 0; | ||
| 251 | 189 | ||
| 252 | epe = cube.epose % 24; | 190 | for (i = 0; is[i] != NULL; i++) { |
| 253 | eps = cube.eposs % 24; | 191 | max *= is[i]->n; |
| 254 | epm = cube.eposm % 24; | 192 | max += is[i]->index(c); |
| 255 | ep = (epe * 24 + eps) *24 + epm; | 193 | } |
| 256 | cp = index_cornershtrfin(cube); | ||
| 257 | 194 | ||
| 258 | return cp * 24 * 24 * 24 + ep; | 195 | return max; |
| 259 | } | 196 | } |
| 260 | 197 | ||
| 261 | static uint64_t | 198 | static void |
| 262 | index_cpud_separate(Cube cube) | 199 | indexers_makecube(Indexer **is, uint64_t ind, Cube *c) |
| 263 | { | 200 | { |
| 264 | return cpud_separate_ind[cube.cp]; | 201 | /* Warning: anti-indexers are applied in the same order as indexers. */ |
| 265 | } | 202 | /* We assume order does not matter, but it would make more sense to */ |
| 203 | /* Apply them in reverse. */ | ||
| 266 | 204 | ||
| 267 | /* Coordinate movers *********************************************************/ | 205 | int i; |
| 206 | uint64_t m; | ||
| 268 | 207 | ||
| 269 | static uint64_t | 208 | make_solved(c); |
| 270 | move_eofb(Move m, uint64_t ind) | 209 | m = indexers_getmax(is); |
| 271 | { | 210 | for (i = 0; is[i] != NULL; i++) { |
| 272 | return eofb_mtable[m][ind]; | 211 | m /= is[i]->n; |
| 212 | is[i]->to_cube(ind / m, c); | ||
| 213 | ind %= m; | ||
| 214 | } | ||
| 273 | } | 215 | } |
| 274 | 216 | ||
| 275 | static uint64_t | 217 | static void |
| 276 | move_eofbepos(Move m, uint64_t ind) | 218 | gen_coord_comp(Coordinate *coord) |
| 277 | { | 219 | { |
| 278 | uint64_t a, b; | 220 | uint64_t ui; |
| 221 | Cube c, mvd; | ||
| 222 | Move m; | ||
| 223 | Trans t; | ||
| 279 | 224 | ||
| 280 | a = epose_mtable[m][(ind / POW2TO11)*24]; | 225 | coord->max = indexers_getmax(coord->i); |
| 281 | b = eofb_mtable[m][ind % POW2TO11]; | ||
| 282 | 226 | ||
| 283 | return (a/24) * POW2TO11 + b; | 227 | for (m = 0; m < NMOVES; m++) |
| 284 | } | 228 | coord->mtable[m] = malloc(coord->max * sizeof(uint64_t)); |
| 285 | 229 | ||
| 286 | static uint64_t | 230 | for (t = 0; t < NTRANS; t++) |
| 287 | move_epud(Move m, uint64_t ind) | 231 | coord->ttable[t] = malloc(coord->max * sizeof(uint64_t)); |
| 288 | { | ||
| 289 | /* TODO: save to file? */ | ||
| 290 | static bool initialized = false; | ||
| 291 | static int a[12] = { [8] = 8, [9] = 9, [10] = 10, [11] = 11 }; | ||
| 292 | static int shortlist[NMOVES] = { | ||
| 293 | [U] = 0, [U2] = 1, [U3] = 2, [D] = 3, [D2] = 4, [D3] = 5, | ||
| 294 | [R2] = 6, [L2] = 7, [F2] = 8, [B2] = 9 | ||
| 295 | }; | ||
| 296 | static uint64_t aux[10][FACTORIAL8]; | ||
| 297 | uint64_t ui; | ||
| 298 | int j; | ||
| 299 | Move mj; | ||
| 300 | Cube c; | ||
| 301 | CubeArray *arr, *auxarr; | ||
| 302 | 232 | ||
| 303 | if (!moveset_drud.allowed(m)) { | 233 | if (!read_coord_mtable(coord)) { |
| 304 | fprintf(stderr, "Move not allowed for epud\n" | 234 | fprintf(stderr, "%s: generating mtable\n", coord->name); |
| 305 | "This is a bug, please report\n"); | ||
| 306 | return coord_epud.max; | ||
| 307 | } | ||
| 308 | 235 | ||
| 309 | if (!initialized) { | 236 | for (ui = 0; ui < coord->max; ui++) { |
| 310 | auxarr = malloc(sizeof(CubeArray)); | 237 | indexers_makecube(coord->i, ui, &c); |
| 311 | auxarr->ep = a; | 238 | for (m = 0; m < NMOVES; m++) { |
| 312 | for (ui = 0; ui < coord_epud.max; ui++) { | 239 | copy_cube(&c, &mvd); |
| 313 | index_to_perm(ui, 8, a); | 240 | apply_move(m, &mvd); |
| 314 | c = arrays_to_cube(auxarr, pf_ep); | 241 | coord->mtable[m][ui] = |
| 315 | for (j = 0; moveset_drud.sorted_moves[j] != NULLMOVE; | 242 | indexers_getind(coord->i, &mvd); |
| 316 | j++) { | ||
| 317 | mj = moveset_drud.sorted_moves[j]; | ||
| 318 | arr = new_cubearray(apply_move(mj, c), pf_ep); | ||
| 319 | aux[shortlist[mj]][ui] = | ||
| 320 | perm_to_index(arr->ep, 8); | ||
| 321 | free_cubearray(arr, pf_ep); | ||
| 322 | } | 243 | } |
| 323 | } | 244 | } |
| 324 | free(auxarr); | 245 | if (!write_coord_mtable(coord)) |
| 325 | 246 | fprintf(stderr, "%s: error writing mtable\n", | |
| 326 | initialized = true; | 247 | coord->name); |
| 248 | |||
| 249 | fprintf(stderr, "%s: mtable generated\n", coord->name); | ||
| 327 | } | 250 | } |
| 328 | 251 | ||
| 329 | return aux[shortlist[m]][ind]; | 252 | if (!read_coord_ttable(coord)) { |
| 330 | } | 253 | fprintf(stderr, "%s: generating ttable\n", coord->name); |
| 331 | 254 | ||
| 332 | static uint64_t | 255 | for (ui = 0; ui < coord->max; ui++) { |
| 333 | move_coud(Move m, uint64_t ind) | 256 | indexers_makecube(coord->i, ui, &c); |
| 334 | { | 257 | for (t = 0; t < NTRANS; t++) { |
| 335 | return coud_mtable[m][ind]; | 258 | copy_cube(&c, &mvd); |
| 259 | apply_trans(t, &mvd); | ||
| 260 | coord->ttable[t][ui] = | ||
| 261 | indexers_getind(coord->i, &mvd); | ||
| 262 | } | ||
| 263 | } | ||
| 264 | if (!write_coord_ttable(coord)) | ||
| 265 | fprintf(stderr, "%s: error writing ttable\n", | ||
| 266 | coord->name); | ||
| 267 | } | ||
| 336 | } | 268 | } |
| 337 | 269 | ||
| 338 | static uint64_t | 270 | static void |
| 339 | move_corners(Move m, uint64_t ind) | 271 | gen_coord_sym(Coordinate *coord) |
| 340 | { | 272 | { |
| 341 | uint64_t a, b; | 273 | uint64_t i, in, ui, uj, uu, M, nr; |
| 274 | int j; | ||
| 275 | Move m; | ||
| 276 | Trans t; | ||
| 342 | 277 | ||
| 343 | a = coud_mtable[m][ind / FACTORIAL8]; | 278 | M = coord->base[0]->max; |
| 344 | b = cp_mtable[m][ind % FACTORIAL8]; | 279 | coord->selfsim = malloc(M * sizeof(uint64_t)); |
| 280 | coord->symclass = malloc(M * sizeof(uint64_t)); | ||
| 281 | coord->symrep = malloc(M * sizeof(uint64_t)); | ||
| 282 | coord->transtorep = malloc(M * sizeof(Trans)); | ||
| 345 | 283 | ||
| 346 | return a * FACTORIAL8 + b; | 284 | if (!read_coord_sd(coord)) { |
| 347 | } | 285 | fprintf(stderr, "%s: generating syms\n", coord->name); |
| 348 | 286 | ||
| 349 | static uint64_t | 287 | for (i = 0; i < M; i++) |
| 350 | move_cp(Move m, uint64_t ind) | 288 | coord->symclass[i] = M+1; |
| 351 | { | ||
| 352 | return cp_mtable[m][ind]; | ||
| 353 | } | ||
| 354 | 289 | ||
| 355 | static uint64_t | 290 | for (i = 0, nr = 0; i < M; i++) { |
| 356 | move_cphtr(Move m, uint64_t ind) | 291 | if (coord->symclass[i] != M+1) |
| 357 | { | 292 | continue; |
| 358 | static bool initialized = false; | 293 | |
| 359 | static uint64_t aux[NMOVES][BINOM8ON4*6]; | 294 | coord->symrep[nr] = i; |
| 360 | uint64_t ui; | 295 | coord->transtorep[i] = uf; |
| 361 | Move j; | 296 | coord->selfsim[nr] = (uint64_t)0; |
| 297 | for (j = 0; j < coord->tgrp->n; j++) { | ||
| 298 | t = coord->tgrp->t[j]; | ||
| 299 | in = trans_coord(coord->base[0], t, i); | ||
| 300 | coord->symclass[in] = nr; | ||
| 301 | if (in == i) | ||
| 302 | coord->selfsim[nr] |= ((uint64_t)1<<t); | ||
| 303 | else | ||
| 304 | coord->transtorep[in] = | ||
| 305 | inverse_trans(t); | ||
| 306 | } | ||
| 307 | nr++; | ||
| 308 | } | ||
| 309 | |||
| 310 | coord->max = nr; | ||
| 311 | |||
| 312 | fprintf(stderr, "%s: found %" PRIu64 " classes\n", | ||
| 313 | coord->name, nr); | ||
| 314 | if (!write_coord_sd(coord)) | ||
| 315 | fprintf(stderr, "%s: error writing symdata\n", | ||
| 316 | coord->name); | ||
| 317 | } | ||
| 362 | 318 | ||
| 363 | if (!initialized) { | 319 | coord->symrep = realloc(coord->symrep, coord->max*sizeof(uint64_t)); |
| 364 | for (ui = 0; ui < BINOM8ON4*6; ui++) | 320 | coord->selfsim = realloc(coord->selfsim, coord->max*sizeof(uint64_t)); |
| 365 | for (j = U; j < NMOVES; j++) | ||
| 366 | aux[j][ui] = cphtr_right_cosets[ | ||
| 367 | cp_mtable[j][cphtr_right_rep[ui]]]; | ||
| 368 | 321 | ||
| 369 | initialized = true; | 322 | for (m = 0; m < NMOVES; m++) { |
| 323 | coord->mtable[m] = malloc(coord->max*sizeof(uint64_t)); | ||
| 324 | coord->ttrep_move[m] = malloc(coord->max*sizeof(Trans)); | ||
| 370 | } | 325 | } |
| 371 | 326 | ||
| 372 | return aux[m][ind]; | 327 | if (!read_coord_mtable(coord)) { |
| 328 | for (ui = 0; ui < coord->max; ui++) { | ||
| 329 | uu = coord->symrep[ui]; | ||
| 330 | for (m = 0; m < NMOVES; m++) { | ||
| 331 | uj = move_coord(coord->base[0], m, uu, NULL); | ||
| 332 | coord->mtable[m][ui] = coord->symclass[uj]; | ||
| 333 | coord->ttrep_move[m][ui] = | ||
| 334 | coord->transtorep[uj]; | ||
| 335 | } | ||
| 336 | } | ||
| 337 | if (!write_coord_mtable(coord)) | ||
| 338 | fprintf(stderr, "%s: error writing mtable\n", | ||
| 339 | coord->name); | ||
| 340 | } | ||
| 373 | } | 341 | } |
| 374 | 342 | ||
| 375 | static uint64_t | 343 | static bool |
| 376 | move_cornershtr(Move m, uint64_t ind) | 344 | read_coord_mtable(Coordinate *coord) |
| 377 | { | 345 | { |
| 378 | uint64_t a, b; | 346 | FILE *f; |
| 347 | char fname[strlen(tabledir)+256]; | ||
| 348 | Move m; | ||
| 349 | uint64_t M; | ||
| 350 | bool r; | ||
| 379 | 351 | ||
| 380 | a = coud_mtable[m][ind/(BINOM8ON4 * 6)]; | 352 | strcpy(fname, tabledir); |
| 381 | b = move_cphtr(m, ind % (BINOM8ON4 * 6)); | 353 | strcat(fname, "/mt_"); |
| 354 | strcat(fname, coord->name); | ||
| 382 | 355 | ||
| 383 | return a * BINOM8ON4 * 6 + b; | 356 | if ((f = fopen(fname, "rb")) == NULL) |
| 384 | } | 357 | return false; |
| 385 | 358 | ||
| 386 | static uint64_t | 359 | M = coord->max; |
| 387 | move_cornershtrfin(Move m, uint64_t ind) | 360 | r = true; |
| 388 | { | 361 | for (m = 0; m < NMOVES; m++) |
| 389 | int a; | 362 | r = r && fread(coord->mtable[m], sizeof(uint64_t), M, f) == M; |
| 390 | 363 | ||
| 391 | a = cp_mtable[m][cornershtrfin_ant[ind]]; | 364 | if (coord->type == SYM_COORD) |
| 365 | for (m = 0; m < NMOVES; m++) | ||
| 366 | r = r && fread(coord->ttrep_move[m], | ||
| 367 | sizeof(Trans), M, f) == M; | ||
| 392 | 368 | ||
| 393 | return cornershtrfin_ind[a]; | 369 | fclose(f); |
| 370 | return r; | ||
| 394 | } | 371 | } |
| 395 | 372 | ||
| 396 | static uint64_t | 373 | static bool |
| 397 | move_drud(Move m, uint64_t ind) | 374 | read_coord_sd(Coordinate *coord) |
| 398 | { | 375 | { |
| 399 | uint64_t a, b, c; | 376 | FILE *f; |
| 377 | char fname[strlen(tabledir)+256]; | ||
| 378 | uint64_t M, N; | ||
| 379 | bool r; | ||
| 380 | |||
| 381 | strcpy(fname, tabledir); | ||
| 382 | strcat(fname, "/sd_"); | ||
| 383 | strcat(fname, coord->name); | ||
| 400 | 384 | ||
| 401 | a = eofb_mtable[m][ind % POW2TO11]; | 385 | if ((f = fopen(fname, "rb")) == NULL) |
| 402 | b = coud_mtable[m][(ind / POW2TO11) % POW3TO7]; | 386 | return false; |
| 403 | c = epose_mtable[m][ind / (POW2TO11 * POW3TO7)]; | ||
| 404 | 387 | ||
| 405 | return a + (b + c * POW3TO7) * POW2TO11; | 388 | r = true; |
| 389 | r = r && fread(&coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 390 | M = coord->max; | ||
| 391 | N = coord->base[0]->max; | ||
| 392 | r = r && fread(coord->symrep, sizeof(uint64_t), M, f) == M; | ||
| 393 | r = r && fread(coord->selfsim, sizeof(uint64_t), M, f) == M; | ||
| 394 | r = r && fread(coord->symclass, sizeof(uint64_t), N, f) == N; | ||
| 395 | r = r && fread(coord->transtorep, sizeof(Trans), N, f) == N; | ||
| 396 | |||
| 397 | fclose(f); | ||
| 398 | return r; | ||
| 406 | } | 399 | } |
| 407 | 400 | ||
| 408 | static uint64_t | 401 | static bool |
| 409 | move_drud_eofb(Move m, uint64_t ind) | 402 | read_coord_ttable(Coordinate *coord) |
| 410 | { | 403 | { |
| 411 | uint64_t a, b; | 404 | FILE *f; |
| 405 | char fname[strlen(tabledir)+256]; | ||
| 406 | Trans t; | ||
| 407 | uint64_t M; | ||
| 408 | bool r; | ||
| 409 | |||
| 410 | strcpy(fname, tabledir); | ||
| 411 | strcat(fname, "/tt_"); | ||
| 412 | strcat(fname, coord->name); | ||
| 412 | 413 | ||
| 413 | a = coud_mtable[m][ind % POW3TO7]; | 414 | if ((f = fopen(fname, "rb")) == NULL) |
| 414 | b = epose_mtable[m][(ind / POW3TO7) * 24] / 24; | 415 | return false; |
| 415 | 416 | ||
| 416 | return a + b * POW3TO7; | 417 | M = coord->max; |
| 418 | r = true; | ||
| 419 | for (t = 0; t < NTRANS; t++) | ||
| 420 | r = r && fread(coord->ttable[t], sizeof(uint64_t), M, f) == M; | ||
| 421 | |||
| 422 | fclose(f); | ||
| 423 | return r; | ||
| 417 | } | 424 | } |
| 418 | 425 | ||
| 419 | static uint64_t | 426 | static bool |
| 420 | move_htr_drud(Move m, uint64_t ind) | 427 | write_coord_mtable(Coordinate *coord) |
| 421 | { | 428 | { |
| 422 | uint64_t a, b; | 429 | FILE *f; |
| 430 | char fname[strlen(tabledir)+256]; | ||
| 431 | Move m; | ||
| 432 | uint64_t M; | ||
| 433 | bool r; | ||
| 434 | |||
| 435 | strcpy(fname, tabledir); | ||
| 436 | strcat(fname, "/mt_"); | ||
| 437 | strcat(fname, coord->name); | ||
| 438 | |||
| 439 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 440 | return false; | ||
| 423 | 441 | ||
| 424 | a = move_cphtr(m, ind/BINOM8ON4); | 442 | M = coord->max; |
| 425 | b = eposs_mtable[m][htr_eposs_ant[ind%BINOM8ON4]]; | 443 | r = true; |
| 444 | for (m = 0; m < NMOVES; m++) | ||
| 445 | r = r && fwrite(coord->mtable[m], sizeof(uint64_t), M, f) == M; | ||
| 426 | 446 | ||
| 427 | return a*BINOM8ON4 + htr_eposs_ind[b/24]; | 447 | if (coord->type == SYM_COORD) |
| 448 | for (m = 0; m < NMOVES; m++) | ||
| 449 | r = r && fwrite(coord->ttrep_move[m], | ||
| 450 | sizeof(Trans), M, f) == M; | ||
| 451 | |||
| 452 | fclose(f); | ||
| 453 | return r; | ||
| 428 | } | 454 | } |
| 429 | 455 | ||
| 430 | static uint64_t | 456 | static bool |
| 431 | move_htrfin(Move m, uint64_t ind) | 457 | write_coord_sd(Coordinate *coord) |
| 432 | { | 458 | { |
| 433 | uint64_t a, b, bm, bs, be; | 459 | FILE *f; |
| 460 | char fname[strlen(tabledir)+256]; | ||
| 461 | uint64_t M, N; | ||
| 462 | bool r; | ||
| 434 | 463 | ||
| 435 | a = move_cornershtrfin(m, ind / (24*24*24)); | 464 | strcpy(fname, tabledir); |
| 436 | bm = eposm_mtable[m][ind%24] % 24; | 465 | strcat(fname, "/sd_"); |
| 437 | bs = eposs_mtable[m][(ind/24)%24] % 24; | 466 | strcat(fname, coord->name); |
| 438 | be = epose_mtable[m][(ind/(24*24))%24] % 24; | ||
| 439 | b = (be * 24 + bs) * 24 + bm; | ||
| 440 | 467 | ||
| 441 | return a * (24*24*24) + b; | 468 | if ((f = fopen(fname, "wb")) == NULL) |
| 469 | return false; | ||
| 470 | |||
| 471 | r = true; | ||
| 472 | M = coord->max; | ||
| 473 | N = coord->base[0]->max; | ||
| 474 | r = r && fwrite(&coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 475 | r = r && fwrite(coord->symrep, sizeof(uint64_t), M, f) == M; | ||
| 476 | r = r && fwrite(coord->selfsim, sizeof(uint64_t), M, f) == M; | ||
| 477 | r = r && fwrite(coord->symclass, sizeof(uint64_t), N, f) == N; | ||
| 478 | r = r && fwrite(coord->transtorep, sizeof(Trans), N, f) == N; | ||
| 479 | |||
| 480 | fclose(f); | ||
| 481 | return r; | ||
| 442 | } | 482 | } |
| 443 | 483 | ||
| 444 | static uint64_t | 484 | static bool |
| 445 | move_cpud_separate(Move m, uint64_t ind) | 485 | write_coord_ttable(Coordinate *coord) |
| 446 | { | 486 | { |
| 447 | return cpud_separate_ind[cp_mtable[m][cpud_separate_ant[ind]]]; | 487 | FILE *f; |
| 488 | char fname[strlen(tabledir)+256]; | ||
| 489 | Trans t; | ||
| 490 | uint64_t M; | ||
| 491 | bool r; | ||
| 492 | |||
| 493 | strcpy(fname, tabledir); | ||
| 494 | strcat(fname, "/tt_"); | ||
| 495 | strcat(fname, coord->name); | ||
| 496 | |||
| 497 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 498 | return false; | ||
| 499 | |||
| 500 | M = coord->max; | ||
| 501 | r = true; | ||
| 502 | for (t = 0; t < NTRANS; t++) | ||
| 503 | r = r && fwrite(coord->ttable[t], sizeof(uint64_t), M, f) == M; | ||
| 504 | |||
| 505 | fclose(f); | ||
| 506 | return r; | ||
| 448 | } | 507 | } |
| 449 | 508 | ||
| 450 | /* Init functions implementation *********************************************/ | 509 | /* Public functions **********************************************************/ |
| 451 | 510 | ||
| 452 | /* | 511 | void |
| 453 | * There is certainly a better way to do this, but for now I just use | 512 | gen_coord(Coordinate *coord) |
| 454 | * a "graph coloring" algorithm to compute the left cosets, and I compose | ||
| 455 | * with every possible cp to get the right cosets (it is possible that I am | ||
| 456 | * mixing up left and right). | ||
| 457 | * | ||
| 458 | * For doing it better "Mathematically", we need 3 things: | ||
| 459 | * - Checking that cp separates the orbits (UFR,UBL,DFL,DBR) and the other | ||
| 460 | * This is easy and it is done in the commented function cphtr_cp(). | ||
| 461 | * - Check that there is no ep/cp parity | ||
| 462 | * - Check that we are not in the "3c" case; this is the part I don't | ||
| 463 | * know how to do. | ||
| 464 | */ | ||
| 465 | static void | ||
| 466 | init_cphtr_cosets() | ||
| 467 | { | 513 | { |
| 468 | unsigned int i; | 514 | int i; |
| 469 | int c = 0, d = 0; | 515 | |
| 516 | if (coord == NULL || coord->generated) | ||
| 517 | return; | ||
| 518 | |||
| 519 | for (i = 0; i < 2; i++) | ||
| 520 | gen_coord(coord->base[i]); | ||
| 470 | 521 | ||
| 471 | for (i = 0; i < FACTORIAL8; i++) { | 522 | switch (coord->type) { |
| 472 | cphtr_left_cosets[i] = -1; | 523 | case COMP_COORD: |
| 473 | cphtr_right_cosets[i] = -1; | 524 | if (coord->i[0] == NULL) |
| 525 | goto error_gc; | ||
| 526 | gen_coord_comp(coord); | ||
| 527 | break; | ||
| 528 | case SYM_COORD: | ||
| 529 | if (coord->base[0] == NULL || coord->tgrp == NULL) | ||
| 530 | goto error_gc; | ||
| 531 | gen_coord_sym(coord); | ||
| 532 | break; | ||
| 533 | case SYMCOMP_COORD: | ||
| 534 | if (coord->base[0] == NULL || coord->base[1] == NULL) | ||
| 535 | goto error_gc; | ||
| 536 | coord->max = coord->base[0]->max * coord->base[1]->max; | ||
| 537 | break; | ||
| 538 | default: | ||
| 539 | break; | ||
| 474 | } | 540 | } |
| 475 | 541 | ||
| 476 | /* First we compute left cosets with a bfs */ | 542 | coord->generated = true; |
| 477 | for (i = 0; i < FACTORIAL8; i++) | 543 | return; |
| 478 | if (cphtr_left_cosets[i] == -1) | ||
| 479 | init_cphtr_left_cosets_bfs(i, c++); | ||
| 480 | 544 | ||
| 481 | /* Then we compute right cosets using compose() */ | 545 | error_gc: |
| 482 | for (i = 0; i < FACTORIAL8; i++) | 546 | fprintf(stderr, "Error generating coordinates.\n" |
| 483 | if (cphtr_right_cosets[i] == -1) | 547 | "This is a bug, pleae report.\n"); |
| 484 | init_cphtr_right_cosets_color(i, d++); | 548 | exit(1); |
| 485 | } | 549 | } |
| 486 | 550 | ||
| 487 | static void | 551 | uint64_t |
| 488 | init_cphtr_left_cosets_bfs(int i, int c) | 552 | index_coord(Coordinate *coord, Cube *cube, Trans *offtrans) |
| 489 | { | 553 | { |
| 490 | int j, jj, next[FACTORIAL8], next2[FACTORIAL8], n, n2; | 554 | uint64_t c[2], cnosym; |
| 555 | Trans ttr; | ||
| 491 | 556 | ||
| 492 | Move k; | 557 | switch (coord->type) { |
| 558 | case COMP_COORD: | ||
| 559 | if (offtrans != NULL) | ||
| 560 | *offtrans = uf; | ||
| 493 | 561 | ||
| 494 | n = 1; | 562 | return indexers_getind(coord->i, cube); |
| 495 | next[0] = i; | 563 | case SYM_COORD: |
| 496 | cphtr_left_cosets[i] = c; | 564 | cnosym = index_coord(coord->base[0], cube, NULL); |
| 565 | ttr = coord->transtorep[cnosym]; | ||
| 497 | 566 | ||
| 498 | while (n != 0) { | 567 | if (offtrans != NULL) |
| 499 | for (j = 0, n2 = 0; j < n; j++) { | 568 | *offtrans = ttr; |
| 500 | for (k = U2; k < B3; k++) { | ||
| 501 | if (!moveset_htr.allowed(k)) | ||
| 502 | continue; | ||
| 503 | jj = apply_move(k, (Cube){ .cp = next[j] }).cp; | ||
| 504 | 569 | ||
| 505 | if (cphtr_left_cosets[jj] == -1) { | 570 | return coord->symclass[cnosym]; |
| 506 | cphtr_left_cosets[jj] = c; | 571 | case SYMCOMP_COORD: |
| 507 | next2[n2++] = jj; | 572 | c[0] = index_coord(coord->base[0], cube, NULL); |
| 508 | } | 573 | cnosym = index_coord(coord->base[0]->base[0], cube, NULL); |
| 509 | } | 574 | ttr = coord->base[0]->transtorep[cnosym]; |
| 510 | } | 575 | c[1] = index_coord(coord->base[1], cube, NULL); |
| 576 | c[1] = trans_coord(coord->base[1], ttr, c[1]); | ||
| 511 | 577 | ||
| 512 | for (j = 0; j < n2; j++) | 578 | if (offtrans != NULL) |
| 513 | next[j] = next2[j]; | 579 | *offtrans = ttr; |
| 514 | n = n2; | 580 | |
| 581 | return c[0] * coord->base[1]->max + c[1]; | ||
| 582 | default: | ||
| 583 | break; | ||
| 515 | } | 584 | } |
| 585 | |||
| 586 | return coord->max; /* Only reached in case of error */ | ||
| 516 | } | 587 | } |
| 517 | 588 | ||
| 518 | static void | 589 | uint64_t |
| 519 | init_cphtr_right_cosets_color(int i, int d) | 590 | move_coord(Coordinate *coord, Move m, uint64_t ind, Trans *offtrans) |
| 520 | { | 591 | { |
| 521 | int cp; | 592 | uint64_t i[2], M; |
| 522 | unsigned int j; | 593 | Trans ttr; |
| 523 | 594 | ||
| 524 | cphtr_right_rep[d] = i; | 595 | /* Some safety checks should be done here, but for performance * |
| 525 | for (j = 0; j < FACTORIAL8; j++) { | 596 | * reasons we'd rather do them before calling this function. * |
| 526 | if (cphtr_left_cosets[j] == 0) { | 597 | * We should check if coord is generated. */ |
| 527 | cp = compose((Cube){.cp = i}, (Cube){.cp = j}).cp; | ||
| 528 | cphtr_right_cosets[cp] = d; | ||
| 529 | } | ||
| 530 | } | ||
| 531 | } | ||
| 532 | 598 | ||
| 533 | static void | 599 | switch (coord->type) { |
| 534 | init_cpud_separate() | 600 | case COMP_COORD: |
| 535 | { | 601 | if (offtrans != NULL) |
| 536 | unsigned int ui; | 602 | *offtrans = uf; |
| 537 | int i, co[8]; | ||
| 538 | 603 | ||
| 539 | for (ui = 0; ui < FACTORIAL8; ui++) { | 604 | return coord->mtable[m][ind]; |
| 540 | for (i = 0; i < 8; i++) | 605 | case SYM_COORD: |
| 541 | co[i] = what_corner_at((Cube){.cp=ui},i)>UBR ? 1 : 0; | 606 | ttr = coord->ttrep_move[m][ind]; |
| 542 | cpud_separate_ind[ui] = subset_to_index(co, 8, 4); | ||
| 543 | cpud_separate_ant[cpud_separate_ind[ui]] = ui; | ||
| 544 | } | ||
| 545 | } | ||
| 546 | 607 | ||
| 547 | static void | 608 | if (offtrans != NULL) |
| 548 | init_cornershtrfin() | 609 | *offtrans = ttr; |
| 549 | { | ||
| 550 | unsigned int i, j; | ||
| 551 | int n, c; | ||
| 552 | Move m; | ||
| 553 | 610 | ||
| 554 | for (i = 0; i < FACTORIAL8; i++) | 611 | return coord->mtable[m][ind]; |
| 555 | cornershtrfin_ind[i] = -1; | 612 | case SYMCOMP_COORD: |
| 556 | cornershtrfin_ind[0] = 0; | 613 | M = coord->base[1]->max; |
| 614 | i[0] = ind / M; | ||
| 615 | i[1] = ind % M; | ||
| 616 | ttr = coord->base[0]->ttrep_move[m][i[0]]; | ||
| 617 | i[0] = coord->base[0]->mtable[m][i[0]]; | ||
| 618 | i[1] = coord->base[1]->mtable[m][i[1]]; | ||
| 619 | i[1] = coord->base[1]->ttable[ttr][i[1]]; | ||
| 557 | 620 | ||
| 558 | /* 10-pass, I think 5 is enough, but just in case */ | 621 | if (offtrans != NULL) |
| 559 | n = 1; | 622 | *offtrans = ttr; |
| 560 | for (i = 0; i < 10; i++) { | 623 | |
| 561 | for (j = 0; j < FACTORIAL8; j++) { | 624 | return i[0] * M + i[1]; |
| 562 | if (cornershtrfin_ind[j] == -1) | 625 | default: |
| 563 | continue; | 626 | break; |
| 564 | for (m = U; m < NMOVES; m++) { | ||
| 565 | if (moveset_htr.allowed(m)) { | ||
| 566 | c = cp_mtable[m][j]; | ||
| 567 | if (cornershtrfin_ind[c] == -1) { | ||
| 568 | cornershtrfin_ind[c] = n; | ||
| 569 | cornershtrfin_ant[n] = c; | ||
| 570 | n++; | ||
| 571 | } | ||
| 572 | } | ||
| 573 | } | ||
| 574 | } | ||
| 575 | } | 627 | } |
| 628 | |||
| 629 | return coord->max; /* Only reached in case of error */ | ||
| 576 | } | 630 | } |
| 577 | 631 | ||
| 578 | void | 632 | bool |
| 579 | init_htr_eposs() | 633 | test_coord(Coordinate *coord) |
| 580 | { | 634 | { |
| 581 | int ep[12], ep2[12]; | 635 | uint64_t ui, uj; |
| 582 | int eps_solved[4] = {UL, UR, DL, DR}; | 636 | Cube c; |
| 583 | unsigned int i, j; | ||
| 584 | 637 | ||
| 585 | for (i = 0; i < BINOM12ON4; i++) { | 638 | if (coord->type != COMP_COORD) { |
| 586 | for (j = 0; j < 12; j++) | 639 | fprintf(stderr, "Can only test COMP_COORD\n"); |
| 587 | ep[j] = ep2[j] = 0; | 640 | return false; |
| 588 | epos_to_partial_ep(i*24, ep, eps_solved); | ||
| 589 | for (j = 0; j < 8; j++) | ||
| 590 | ep2[j/2 + 4*(j%2)] = ep[j] ? 1 : 0; | ||
| 591 | htr_eposs_ind[i] = subset_to_index(ep2, 8, 4); | ||
| 592 | htr_eposs_ant[htr_eposs_ind[i]] = i*24; | ||
| 593 | } | 641 | } |
| 642 | |||
| 643 | gen_coord(coord); | ||
| 644 | for (ui = 0; ui < coord->max; ui++) { | ||
| 645 | indexers_makecube(coord->i, ui, &c); | ||
| 646 | uj = indexers_getind(coord->i, &c); | ||
| 647 | if (ui != uj) { | ||
| 648 | fprintf(stderr, "%s: error: %" PRIu64 " different" | ||
| 649 | " from %" PRIu64 "\n", coord->name, uj, ui); | ||
| 650 | return false; | ||
| 651 | } | ||
| 652 | } | ||
| 653 | |||
| 654 | fprintf(stderr, "%s: test passed\n", coord->name); | ||
| 655 | return true; | ||
| 594 | } | 656 | } |
| 595 | 657 | ||
| 596 | void | 658 | uint64_t |
| 597 | init_coord() | 659 | trans_coord(Coordinate *coord, Trans t, uint64_t ind) |
| 598 | { | 660 | { |
| 599 | static bool initialized = false; | 661 | uint64_t i[2], M; |
| 600 | if (initialized) | ||
| 601 | return; | ||
| 602 | initialized = true; | ||
| 603 | 662 | ||
| 604 | init_trans(); | 663 | /* Some safety checks should be done here, but for performance * |
| 664 | * reasons we'd rather do them before calling this function. * | ||
| 665 | * We should check if coord is generated. */ | ||
| 605 | 666 | ||
| 606 | init_cphtr_cosets(); | 667 | switch (coord->type) { |
| 607 | init_cornershtrfin(); | 668 | case COMP_COORD: |
| 608 | init_htr_eposs(); | 669 | return coord->ttable[t][ind]; |
| 609 | init_cpud_separate(); | 670 | case SYM_COORD: |
| 610 | } | 671 | return ind; |
| 672 | case SYMCOMP_COORD: | ||
| 673 | M = coord->base[1]->max; | ||
| 674 | i[0] = ind / M; /* Always fixed */ | ||
| 675 | i[1] = ind % M; | ||
| 676 | i[1] = coord->base[1]->ttable[t][i[1]]; | ||
| 677 | return i[0] * M + i[1]; | ||
| 678 | default: | ||
| 679 | break; | ||
| 680 | } | ||
| 611 | 681 | ||
| 682 | return coord->max; /* Only reached in case of error */ | ||
| 683 | } | ||
diff --git a/src/coord.h b/src/coord.h index 61398a4..47c0579 100644 --- a/src/coord.h +++ b/src/coord.h | |||
| @@ -3,26 +3,232 @@ | |||
| 3 | 3 | ||
| 4 | #include "trans.h" | 4 | #include "trans.h" |
| 5 | 5 | ||
| 6 | extern Coordinate coord_eofb; | 6 | void gen_coord(Coordinate *coord); |
| 7 | extern Coordinate coord_eofbepos; | 7 | uint64_t index_coord(Coordinate *coord, Cube *cube, |
| 8 | extern Coordinate coord_coud; | 8 | Trans *offtrans); |
| 9 | extern Coordinate coord_cp; | 9 | uint64_t move_coord(Coordinate *coord, Move m, |
| 10 | extern Coordinate coord_cphtr; | 10 | uint64_t ind, Trans *offtrans); |
| 11 | extern Coordinate coord_corners; | 11 | bool test_coord(Coordinate *coord); |
| 12 | extern Coordinate coord_cornershtr; | 12 | uint64_t trans_coord(Coordinate *coord, Trans t, uint64_t ind); |
| 13 | extern Coordinate coord_cornershtrfin; | ||
| 14 | extern Coordinate coord_epud; | ||
| 15 | extern Coordinate coord_drud; | ||
| 16 | extern Coordinate coord_drud_eofb; | ||
| 17 | extern Coordinate coord_htr_drud; | ||
| 18 | extern Coordinate coord_htrfin; | ||
| 19 | extern Coordinate coord_cpud_separate; | ||
| 20 | 13 | ||
| 21 | extern int cpud_separate_ant[BINOM8ON4]; | 14 | /* Base coordinates and their index functions ********************************/ |
| 22 | extern int cpud_separate_ind[FACTORIAL8]; | ||
| 23 | extern int cornershtrfin_ant[24*24/6]; | ||
| 24 | 15 | ||
| 25 | void init_coord(); | 16 | #ifndef COORD_C |
| 17 | |||
| 18 | extern Coordinate coord_eofb; | ||
| 19 | extern Coordinate coord_coud; | ||
| 20 | extern Coordinate coord_cp; | ||
| 21 | extern Coordinate coord_cpudsep; | ||
| 22 | extern Coordinate coord_epos; | ||
| 23 | extern Coordinate coord_epe; | ||
| 24 | extern Coordinate coord_eposepe; | ||
| 25 | extern Coordinate coord_epud; | ||
| 26 | extern Coordinate coord_eofbepos; | ||
| 27 | extern Coordinate coord_coud_cpudsep; | ||
| 28 | extern Coordinate coord_eofbepos_sym16; | ||
| 29 | extern Coordinate coord_cp_sym16; | ||
| 30 | extern Coordinate coord_corners_sym16; | ||
| 31 | extern Coordinate coord_drud_sym16; | ||
| 32 | extern Coordinate coord_drudfin_noE_sym16; | ||
| 33 | extern Coordinate coord_nxopt31; | ||
| 34 | |||
| 35 | #else | ||
| 36 | |||
| 37 | /* Indexers ******************************************************************/ | ||
| 38 | |||
| 39 | uint64_t index_eofb(Cube *cube); | ||
| 40 | void invindex_eofb(uint64_t ind, Cube *ret); | ||
| 41 | Indexer | ||
| 42 | i_eofb = { | ||
| 43 | .n = POW2TO11, | ||
| 44 | .index = index_eofb, | ||
| 45 | .to_cube = invindex_eofb, | ||
| 46 | }; | ||
| 47 | |||
| 48 | uint64_t index_coud(Cube *cube); | ||
| 49 | void invindex_coud(uint64_t ind, Cube *ret); | ||
| 50 | Indexer | ||
| 51 | i_coud = { | ||
| 52 | .n = POW3TO7, | ||
| 53 | .index = index_coud, | ||
| 54 | .to_cube = invindex_coud, | ||
| 55 | }; | ||
| 56 | |||
| 57 | uint64_t index_cp(Cube *cube); | ||
| 58 | void invindex_cp(uint64_t ind, Cube *ret); | ||
| 59 | Indexer | ||
| 60 | i_cp = { | ||
| 61 | .n = FACTORIAL8, | ||
| 62 | .index = index_cp, | ||
| 63 | .to_cube = invindex_cp, | ||
| 64 | }; | ||
| 65 | |||
| 66 | uint64_t index_cpudsep(Cube *cube); | ||
| 67 | void invindex_cpudsep(uint64_t ind, Cube *ret); | ||
| 68 | Indexer | ||
| 69 | i_cpudsep = { | ||
| 70 | .n = BINOM8ON4, | ||
| 71 | .index = index_cpudsep, | ||
| 72 | .to_cube = invindex_cpudsep, | ||
| 73 | }; | ||
| 74 | |||
| 75 | uint64_t index_epos(Cube *cube); | ||
| 76 | void invindex_epos(uint64_t ind, Cube *ret); | ||
| 77 | Indexer | ||
| 78 | i_epos = { | ||
| 79 | .n = BINOM12ON4, | ||
| 80 | .index = index_epos, | ||
| 81 | .to_cube = invindex_epos, | ||
| 82 | }; | ||
| 83 | |||
| 84 | uint64_t index_epe(Cube *cube); | ||
| 85 | void invindex_epe(uint64_t ind, Cube *ret); | ||
| 86 | Indexer | ||
| 87 | i_epe = { | ||
| 88 | .n = FACTORIAL4, | ||
| 89 | .index = index_epe, | ||
| 90 | .to_cube = invindex_epe, | ||
| 91 | }; | ||
| 92 | |||
| 93 | uint64_t index_eposepe(Cube *cube); | ||
| 94 | void invindex_eposepe(uint64_t ind, Cube *ret); | ||
| 95 | Indexer | ||
| 96 | i_eposepe = { | ||
| 97 | .n = BINOM12ON4 * FACTORIAL4, | ||
| 98 | .index = index_eposepe, | ||
| 99 | .to_cube = invindex_eposepe, | ||
| 100 | }; | ||
| 101 | |||
| 102 | uint64_t index_epud(Cube *cube); | ||
| 103 | void invindex_epud(uint64_t ind, Cube *ret); | ||
| 104 | Indexer | ||
| 105 | i_epud = { | ||
| 106 | .n = FACTORIAL8, | ||
| 107 | .index = index_epud, | ||
| 108 | .to_cube = invindex_epud, | ||
| 109 | }; | ||
| 110 | |||
| 111 | /* Composite coordinates *****************************************************/ | ||
| 112 | |||
| 113 | Coordinate | ||
| 114 | coord_eofb = { | ||
| 115 | .name = "eofb", | ||
| 116 | .type = COMP_COORD, | ||
| 117 | .i = {&i_eofb, NULL}, | ||
| 118 | }; | ||
| 119 | |||
| 120 | Coordinate | ||
| 121 | coord_coud = { | ||
| 122 | .name = "coud", | ||
| 123 | .type = COMP_COORD, | ||
| 124 | .i = {&i_coud, NULL}, | ||
| 125 | }; | ||
| 126 | |||
| 127 | Coordinate | ||
| 128 | coord_cp = { | ||
| 129 | .name = "cp", | ||
| 130 | .type = COMP_COORD, | ||
| 131 | .i = {&i_cp, NULL}, | ||
| 132 | }; | ||
| 133 | |||
| 134 | Coordinate | ||
| 135 | coord_cpudsep = { | ||
| 136 | .name = "cpudsep", | ||
| 137 | .type = COMP_COORD, | ||
| 138 | .i = {&i_cpudsep, NULL}, | ||
| 139 | }; | ||
| 140 | |||
| 141 | Coordinate | ||
| 142 | coord_epos = { | ||
| 143 | .name = "epos", | ||
| 144 | .type = COMP_COORD, | ||
| 145 | .i = {&i_epos, NULL}, | ||
| 146 | }; | ||
| 147 | |||
| 148 | Coordinate | ||
| 149 | coord_epe = { | ||
| 150 | .name = "epe", | ||
| 151 | .type = COMP_COORD, | ||
| 152 | .i = {&i_epe, NULL}, | ||
| 153 | }; | ||
| 154 | |||
| 155 | Coordinate | ||
| 156 | coord_eposepe = { /* Has to be done by hand, hard compose epos + epe */ | ||
| 157 | .name = "eposepe", | ||
| 158 | .type = COMP_COORD, | ||
| 159 | .i = {&i_eposepe, NULL}, | ||
| 160 | }; | ||
| 161 | |||
| 162 | Coordinate | ||
| 163 | coord_epud = { | ||
| 164 | .name = "epud", | ||
| 165 | .type = COMP_COORD, | ||
| 166 | .i = {&i_epud, NULL}, | ||
| 167 | }; | ||
| 168 | |||
| 169 | Coordinate | ||
| 170 | coord_eofbepos = { | ||
| 171 | .name = "eofbepos", | ||
| 172 | .type = COMP_COORD, | ||
| 173 | .i = {&i_epos, &i_eofb, NULL}, | ||
| 174 | }; | ||
| 175 | |||
| 176 | Coordinate | ||
| 177 | coord_coud_cpudsep = { | ||
| 178 | .name = "coud_cpudsep", | ||
| 179 | .type = COMP_COORD, | ||
| 180 | .i = {&i_coud, &i_cpudsep, NULL}, | ||
| 181 | }; | ||
| 182 | |||
| 183 | /* Symcoordinates ************************************************************/ | ||
| 184 | |||
| 185 | Coordinate | ||
| 186 | coord_eofbepos_sym16 = { | ||
| 187 | .name = "eofbepos_sym16", | ||
| 188 | .type = SYM_COORD, | ||
| 189 | .base = {&coord_eofbepos, NULL}, | ||
| 190 | .tgrp = &tgrp_udfix, | ||
| 191 | }; | ||
| 192 | |||
| 193 | Coordinate | ||
| 194 | coord_cp_sym16 = { | ||
| 195 | .name = "cp_sym16", | ||
| 196 | .type = SYM_COORD, | ||
| 197 | .base = {&coord_cp, NULL}, | ||
| 198 | .tgrp = &tgrp_udfix, | ||
| 199 | }; | ||
| 200 | |||
| 201 | /* "Symcomp" coordinates *****************************************************/ | ||
| 202 | |||
| 203 | Coordinate | ||
| 204 | coord_corners_sym16 = { | ||
| 205 | .name = "corners_sym16", | ||
| 206 | .type = SYMCOMP_COORD, | ||
| 207 | .base = {&coord_cp_sym16, &coord_coud}, | ||
| 208 | }; | ||
| 209 | |||
| 210 | Coordinate | ||
| 211 | coord_drud_sym16 = { | ||
| 212 | .name = "drud_sym16", | ||
| 213 | .type = SYMCOMP_COORD, | ||
| 214 | .base = {&coord_eofbepos_sym16, &coord_coud}, | ||
| 215 | }; | ||
| 216 | |||
| 217 | Coordinate | ||
| 218 | coord_drudfin_noE_sym16 = { | ||
| 219 | .name = "drudfin_noE_sym16", | ||
| 220 | .type = SYMCOMP_COORD, | ||
| 221 | .base = {&coord_cp_sym16, &coord_epud}, | ||
| 222 | }; | ||
| 223 | |||
| 224 | Coordinate | ||
| 225 | coord_nxopt31 = { | ||
| 226 | .name = "nxopt31", | ||
| 227 | .type = SYMCOMP_COORD, | ||
| 228 | .base = {&coord_eofbepos_sym16, &coord_coud_cpudsep}, | ||
| 229 | }; | ||
| 230 | |||
| 231 | #endif | ||
| 26 | 232 | ||
| 27 | #endif | 233 | #endif |
| 28 | 234 | ||
| @@ -1,531 +1,121 @@ | |||
| 1 | #include "cube.h" | 1 | #define CUBE_C |
| 2 | |||
| 3 | /* Local functions ***********************************************************/ | ||
| 4 | |||
| 5 | static void init_inverse(); | ||
| 6 | static bool read_invtables_file(); | ||
| 7 | static bool write_invtables_file(); | ||
| 8 | |||
| 9 | /* Tables ********************************************************************/ | ||
| 10 | |||
| 11 | static uint16_t eo_invtable_e[POW2TO11][BINOM12ON4*FACTORIAL4]; | ||
| 12 | static uint16_t eo_invtable_s[POW2TO11][BINOM12ON4*FACTORIAL4]; | ||
| 13 | static uint16_t eo_invtable_m[POW2TO11][BINOM12ON4*FACTORIAL4]; | ||
| 14 | static uint16_t co_invtable[POW3TO7][FACTORIAL8]; | ||
| 15 | static uint16_t cp_invtable[FACTORIAL8]; | ||
| 16 | static uint16_t cpos_invtable[FACTORIAL6]; | ||
| 17 | |||
| 18 | /* Functions implementation **************************************************/ | ||
| 19 | |||
| 20 | int | ||
| 21 | array_ep_to_epos(int *ep, int *ss) | ||
| 22 | { | ||
| 23 | int epos[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 24 | int eps[4]; | ||
| 25 | int i, j, is; | ||
| 26 | |||
| 27 | for (i = 0, is = 0; i < 12; i++) { | ||
| 28 | for (j = 0; j < 4; j++) { | ||
| 29 | if (ep[i] == ss[j]) { | ||
| 30 | eps[is++] = j; | ||
| 31 | epos[i] = 1; | ||
| 32 | } | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | for (i = 0; i < 4; i++) | ||
| 37 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 38 | |||
| 39 | return 24 * subset_to_index(epos, 12, 4) + perm_to_index(eps, 4); | ||
| 40 | } | ||
| 41 | |||
| 42 | Cube | ||
| 43 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 44 | { | ||
| 45 | Cube ret = {0}; | ||
| 46 | |||
| 47 | static int epe_solved[4] = {FR, FL, BL, BR}; | ||
| 48 | static int eps_solved[4] = {UL, UR, DL, DR}; | ||
| 49 | static int epm_solved[4] = {UF, UB, DF, DB}; | ||
| 50 | 2 | ||
| 51 | if (f.epose) | 3 | #include "cube.h" |
| 52 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 53 | if (f.eposs) | ||
| 54 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 55 | if (f.eposm) | ||
| 56 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 57 | if (f.eofb) | ||
| 58 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 59 | if (f.eorl) | ||
| 60 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 61 | if (f.eoud) | ||
| 62 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 63 | if (f.cp) | ||
| 64 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 65 | if (f.coud) | ||
| 66 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 67 | if (f.corl) | ||
| 68 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 69 | if (f.cofb) | ||
| 70 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 71 | if (f.cpos) | ||
| 72 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 73 | |||
| 74 | return ret; | ||
| 75 | } | ||
| 76 | 4 | ||
| 77 | Cube | 5 | void |
| 78 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | 6 | compose(Cube *c2, Cube *c1) |
| 79 | { | 7 | { |
| 80 | CubeArray *arr = new_cubearray(c2, f); | 8 | apply_permutation(c2->ep, c1->ep, 12); |
| 81 | Cube ret; | 9 | apply_permutation(c2->ep, c1->eo, 12); |
| 10 | sum_arrays_mod(c2->eo, c1->eo, 12, 2); | ||
| 82 | 11 | ||
| 83 | ret = move_via_arrays(arr, c1, f); | 12 | apply_permutation(c2->cp, c1->cp, 8); |
| 84 | free_cubearray(arr, f); | 13 | apply_permutation(c2->cp, c1->co, 8); |
| 14 | sum_arrays_mod(c2->co, c1->co, 8, 3); | ||
| 85 | 15 | ||
| 86 | return ret; | 16 | apply_permutation(c2->xp, c1->xp, 6); |
| 87 | } | 17 | } |
| 88 | 18 | ||
| 89 | void | 19 | void |
| 90 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | 20 | copy_cube(Cube *src, Cube *dst) |
| 91 | { | 21 | { |
| 92 | int i; | 22 | memcpy(dst->ep, src->ep, 12 * sizeof(int)); |
| 93 | 23 | memcpy(dst->eo, src->eo, 12 * sizeof(int)); | |
| 94 | static int epe_solved[4] = {FR, FL, BL, BR}; | 24 | memcpy(dst->cp, src->cp, 8 * sizeof(int)); |
| 95 | static int eps_solved[4] = {UL, UR, DL, DR}; | 25 | memcpy(dst->co, src->co, 8 * sizeof(int)); |
| 96 | static int epm_solved[4] = {UF, UB, DF, DB}; | 26 | memcpy(dst->xp, src->xp, 6 * sizeof(int)); |
| 97 | |||
| 98 | if (f.epose || f.eposs || f.eposm) | ||
| 99 | for (i = 0; i < 12; i++) | ||
| 100 | arr->ep[i] = -1; | ||
| 101 | |||
| 102 | if (f.epose) | ||
| 103 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 104 | if (f.eposs) | ||
| 105 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 106 | if (f.eposm) | ||
| 107 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 108 | if (f.eofb) | ||
| 109 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 110 | if (f.eorl) | ||
| 111 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 112 | if (f.eoud) | ||
| 113 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 114 | if (f.cp) | ||
| 115 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 116 | if (f.coud) | ||
| 117 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 118 | if (f.corl) | ||
| 119 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 120 | if (f.cofb) | ||
| 121 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 122 | if (f.cpos) | ||
| 123 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 124 | } | 27 | } |
| 125 | 28 | ||
| 126 | void | 29 | bool |
| 127 | epos_to_compatible_ep(int epos, int *ep, int *ss) | 30 | equal(Cube *c1, Cube *c2) |
| 128 | { | 31 | { |
| 129 | int i, j, k, other[8]; | 32 | int i; |
| 130 | bool flag; | ||
| 131 | 33 | ||
| 132 | for (i = 0; i < 12; i++) | 34 | for (i = 0; i < 12; i++) |
| 133 | ep[i] = -1; | 35 | if (c1->ep[i] != c2->ep[i] || c1->eo[i] != c2->eo[i]) |
| 134 | 36 | return false; | |
| 135 | epos_to_partial_ep(epos, ep, ss); | ||
| 136 | |||
| 137 | for (i = 0, j = 0; i < 12; i++) { | ||
| 138 | flag = false; | ||
| 139 | for (k = 0; k < 4; k++) | ||
| 140 | flag = flag || (i == ss[k]); | ||
| 141 | if (!flag) | ||
| 142 | other[j++] = i; | ||
| 143 | } | ||
| 144 | |||
| 145 | for (i = 0, j = 0; i < 12; i++) | ||
| 146 | if (ep[i] == -1) | ||
| 147 | ep[i] = other[j++]; | ||
| 148 | } | ||
| 149 | |||
| 150 | void | ||
| 151 | epos_to_partial_ep(int epos, int *ep, int *ss) | ||
| 152 | { | ||
| 153 | int i, is, eposs[12], eps[4]; | ||
| 154 | 37 | ||
| 155 | index_to_perm(epos % FACTORIAL4, 4, eps); | 38 | for (i = 0; i < 8; i++) |
| 156 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | 39 | if (c1->cp[i] != c2->cp[i] || c1->co[i] != c2->co[i]) |
| 40 | return false; | ||
| 157 | 41 | ||
| 158 | for (i = 0; i < 4; i++) | 42 | for (i = 0; i < 6; i++) |
| 159 | swap(&eposs[ss[i]], &eposs[i+8]); | 43 | if (c1->xp[i] != c2->xp[i]) |
| 44 | return false; | ||
| 160 | 45 | ||
| 161 | for (i = 0, is = 0; i < 12; i++) | 46 | return true; |
| 162 | if (eposs[i]) | ||
| 163 | ep[i] = ss[eps[is++]]; | ||
| 164 | } | 47 | } |
| 165 | 48 | ||
| 166 | void | 49 | void |
| 167 | fix_eorleoud(CubeArray *arr) | 50 | invert_cube(Cube *cube) |
| 168 | { | 51 | { |
| 52 | Cube aux; | ||
| 169 | int i; | 53 | int i; |
| 170 | 54 | ||
| 171 | for (i = 0; i < 12; i++) { | 55 | copy_cube(cube, &aux); |
| 172 | if ((edge_slice(i) == 0 && edge_slice(arr->ep[i]) != 0) || | ||
| 173 | (edge_slice(i) != 0 && edge_slice(arr->ep[i]) == 0)) { | ||
| 174 | arr->eorl[i] = 1 - arr->eofb[i]; | ||
| 175 | } else { | ||
| 176 | arr->eorl[i] = arr->eofb[i]; | ||
| 177 | } | ||
| 178 | 56 | ||
| 179 | if ((edge_slice(i) == 2 && edge_slice(arr->ep[i]) != 2) || | 57 | for (i = 0; i < 12; i++) { |
| 180 | (edge_slice(i) != 2 && edge_slice(arr->ep[i]) == 2)) { | 58 | cube->ep[aux.ep[i]] = i; |
| 181 | arr->eoud[i] = 1 - arr->eofb[i]; | 59 | cube->eo[aux.ep[i]] = aux.eo[i]; |
| 182 | } else { | ||
| 183 | arr->eoud[i] = arr->eofb[i]; | ||
| 184 | } | ||
| 185 | } | 60 | } |
| 186 | } | ||
| 187 | |||
| 188 | void | ||
| 189 | fix_cofbcorl(CubeArray *arr) | ||
| 190 | { | ||
| 191 | int i; | ||
| 192 | 61 | ||
| 193 | for (i = 0; i < 8; i++) { | 62 | for (i = 0; i < 8; i++) { |
| 194 | if (i % 2 == arr->cp[i] % 2) { | 63 | cube->cp[aux.cp[i]] = i; |
| 195 | arr->cofb[i] = arr->coud[i]; | 64 | cube->co[aux.cp[i]] = (3 - aux.co[i]) % 3; |
| 196 | arr->corl[i] = arr->coud[i]; | ||
| 197 | } else { | ||
| 198 | if (arr->cp[i] % 2 == 0) { | ||
| 199 | arr->cofb[i] = (arr->coud[i]+1)%3; | ||
| 200 | arr->corl[i] = (arr->coud[i]+2)%3; | ||
| 201 | } else { | ||
| 202 | arr->cofb[i] = (arr->coud[i]+2)%3; | ||
| 203 | arr->corl[i] = (arr->coud[i]+1)%3; | ||
| 204 | } | ||
| 205 | } | ||
| 206 | } | 65 | } |
| 207 | } | ||
| 208 | |||
| 209 | Cube | ||
| 210 | fourval_to_cube(int eofb, int ep, int coud, int cp) | ||
| 211 | { | ||
| 212 | CubeArray *arr; | ||
| 213 | |||
| 214 | arr = new_cubearray((Cube){0}, pf_all); | ||
| 215 | 66 | ||
| 216 | index_to_perm(ep, 12, arr->ep); | 67 | for (i = 0; i < 6; i++) |
| 217 | index_to_perm(cp, 8, arr->cp); | 68 | cube->xp[aux.xp[i]] = i; |
| 218 | int_to_sum_zero_array(eofb, 2, 12, arr->eofb); | ||
| 219 | int_to_sum_zero_array(coud, 3, 8, arr->coud); | ||
| 220 | |||
| 221 | /* fix parity */ | ||
| 222 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 223 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 224 | |||
| 225 | fix_eorleoud(arr); | ||
| 226 | fix_cofbcorl(arr); | ||
| 227 | |||
| 228 | return arrays_to_cube(arr, pf_all); | ||
| 229 | } | ||
| 230 | |||
| 231 | void | ||
| 232 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 233 | { | ||
| 234 | if (f.epose || f.eposs || f.eposm) | ||
| 235 | free(arr->ep); | ||
| 236 | if (f.eofb) | ||
| 237 | free(arr->eofb); | ||
| 238 | if (f.eorl) | ||
| 239 | free(arr->eorl); | ||
| 240 | if (f.eoud) | ||
| 241 | free(arr->eoud); | ||
| 242 | if (f.cp) | ||
| 243 | free(arr->cp); | ||
| 244 | if (f.coud) | ||
| 245 | free(arr->coud); | ||
| 246 | if (f.corl) | ||
| 247 | free(arr->corl); | ||
| 248 | if (f.cofb) | ||
| 249 | free(arr->cofb); | ||
| 250 | if (f.cpos) | ||
| 251 | free(arr->cpos); | ||
| 252 | |||
| 253 | free(arr); | ||
| 254 | } | ||
| 255 | |||
| 256 | Cube | ||
| 257 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 258 | { | ||
| 259 | CubeArray *arrc = new_cubearray(c, f); | ||
| 260 | Cube ret; | ||
| 261 | |||
| 262 | if (f.epose || f.eposs || f.eposm) | ||
| 263 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 264 | |||
| 265 | if (f.eofb) { | ||
| 266 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 267 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 268 | } | ||
| 269 | |||
| 270 | if (f.eorl) { | ||
| 271 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 272 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 273 | } | ||
| 274 | |||
| 275 | if (f.eoud) { | ||
| 276 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 277 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 278 | } | ||
| 279 | |||
| 280 | if (f.cp) | ||
| 281 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 282 | |||
| 283 | if (f.coud) { | ||
| 284 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 285 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 286 | } | ||
| 287 | |||
| 288 | if (f.corl) { | ||
| 289 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 290 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 291 | } | ||
| 292 | |||
| 293 | if (f.cofb) { | ||
| 294 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 295 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 296 | } | ||
| 297 | |||
| 298 | if (f.cpos) | ||
| 299 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 300 | |||
| 301 | ret = arrays_to_cube(arrc, f); | ||
| 302 | free_cubearray(arrc, f); | ||
| 303 | |||
| 304 | return ret; | ||
| 305 | } | ||
| 306 | |||
| 307 | CubeArray * | ||
| 308 | new_cubearray(Cube cube, PieceFilter f) | ||
| 309 | { | ||
| 310 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 311 | |||
| 312 | if (f.epose || f.eposs || f.eposm) | ||
| 313 | arr->ep = malloc(12 * sizeof(int)); | ||
| 314 | if (f.eofb) | ||
| 315 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 316 | if (f.eorl) | ||
| 317 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 318 | if (f.eoud) | ||
| 319 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 320 | if (f.cp) | ||
| 321 | arr->cp = malloc(8 * sizeof(int)); | ||
| 322 | if (f.coud) | ||
| 323 | arr->coud = malloc(8 * sizeof(int)); | ||
| 324 | if (f.corl) | ||
| 325 | arr->corl = malloc(8 * sizeof(int)); | ||
| 326 | if (f.cofb) | ||
| 327 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 328 | if (f.cpos) | ||
| 329 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 330 | |||
| 331 | cube_to_arrays(cube, arr, f); | ||
| 332 | |||
| 333 | return arr; | ||
| 334 | } | ||
| 335 | |||
| 336 | Cube | ||
| 337 | admissible_ep(Cube cube, PieceFilter f) | ||
| 338 | { | ||
| 339 | CubeArray *arr = new_cubearray(cube, f); | ||
| 340 | Cube ret; | ||
| 341 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 342 | int i, j; | ||
| 343 | |||
| 344 | for (i = 0; i < 12; i++) | ||
| 345 | if (arr->ep[i] != -1) | ||
| 346 | used[arr->ep[i]] = true; | ||
| 347 | |||
| 348 | for (i = 0, j = 0; i < 12; i++) { | ||
| 349 | for ( ; j < 11 && used[j]; j++); | ||
| 350 | if (arr->ep[i] == -1) | ||
| 351 | arr->ep[i] = j++; | ||
| 352 | } | ||
| 353 | |||
| 354 | ret = arrays_to_cube(arr, pf_ep); | ||
| 355 | free_cubearray(arr, f); | ||
| 356 | |||
| 357 | return ret; | ||
| 358 | } | ||
| 359 | |||
| 360 | Cube | ||
| 361 | compose(Cube c2, Cube c1) | ||
| 362 | { | ||
| 363 | return compose_filtered(c2, c1, pf_all); | ||
| 364 | } | ||
| 365 | |||
| 366 | int | ||
| 367 | edge_slice(Edge e) { | ||
| 368 | if (e < 0 || e > 11) | ||
| 369 | return -1; | ||
| 370 | |||
| 371 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 372 | return 0; | ||
| 373 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 374 | return 1; | ||
| 375 | |||
| 376 | return 2; | ||
| 377 | } | ||
| 378 | |||
| 379 | bool | ||
| 380 | equal(Cube c1, Cube c2) | ||
| 381 | { | ||
| 382 | return c1.eofb == c2.eofb && | ||
| 383 | c1.epose == c2.epose && | ||
| 384 | c1.eposs == c2.eposs && | ||
| 385 | c1.eposm == c2.eposm && | ||
| 386 | c1.coud == c2.coud && | ||
| 387 | c1.cp == c2.cp && | ||
| 388 | c1.cpos == c2.cpos; | ||
| 389 | } | ||
| 390 | |||
| 391 | Cube | ||
| 392 | inverse_cube(Cube cube) | ||
| 393 | { | ||
| 394 | CubeArray inv; | ||
| 395 | Cube ret; | ||
| 396 | int i, ep[12]; | ||
| 397 | |||
| 398 | for (i = 0; i < 12; i++) | ||
| 399 | ep[i] = where_is_edge(cube, i); | ||
| 400 | inv = (CubeArray){.ep = ep}; | ||
| 401 | ret = arrays_to_cube(&inv, pf_ep); | ||
| 402 | |||
| 403 | ret.eofb = ((int)eo_invtable_e[cube.eofb][cube.epose]) | | ||
| 404 | ((int)eo_invtable_m[cube.eofb][cube.eposm]) | | ||
| 405 | ((int)eo_invtable_s[cube.eofb][cube.eposs]); | ||
| 406 | ret.eorl = ((int)eo_invtable_e[cube.eorl][cube.epose]) | | ||
| 407 | ((int)eo_invtable_m[cube.eorl][cube.eposm]) | | ||
| 408 | ((int)eo_invtable_s[cube.eorl][cube.eposs]); | ||
| 409 | ret.eoud = ((int)eo_invtable_e[cube.eoud][cube.epose]) | | ||
| 410 | ((int)eo_invtable_m[cube.eoud][cube.eposm]) | | ||
| 411 | ((int)eo_invtable_s[cube.eoud][cube.eposs]); | ||
| 412 | ret.cp = cp_invtable[cube.cp]; | ||
| 413 | ret.cpos = cpos_invtable[cube.cpos]; | ||
| 414 | ret.coud = co_invtable[cube.coud][cube.cp]; | ||
| 415 | ret.corl = co_invtable[cube.corl][cube.cp]; | ||
| 416 | ret.cofb = co_invtable[cube.cofb][cube.cp]; | ||
| 417 | |||
| 418 | return ret; | ||
| 419 | } | 69 | } |
| 420 | 70 | ||
| 421 | bool | 71 | bool |
| 422 | is_admissible(Cube cube) { | 72 | is_admissible(Cube *c) { |
| 423 | |||
| 424 | /* TODO: this should check consistency of different orientations */ | ||
| 425 | /* check also that centers are opposite and admissible */ | ||
| 426 | |||
| 427 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 428 | int parity; | ||
| 429 | bool perm; | 73 | bool perm; |
| 74 | int sign, i; | ||
| 75 | int sum_e, sum_c; | ||
| 430 | 76 | ||
| 431 | perm = is_perm(a->ep, 12) && | 77 | perm = is_perm(c->ep, 12) && is_perm(c->cp, 8) && is_perm(c->xp, 6); |
| 432 | is_perm(a->cp, 8) && | ||
| 433 | is_perm(a->cpos, 6); | ||
| 434 | parity = perm_sign(a->ep, 12) + | ||
| 435 | perm_sign(a->cp, 8) + | ||
| 436 | perm_sign(a->cpos, 6); | ||
| 437 | |||
| 438 | free_cubearray(a, pf_all); | ||
| 439 | 78 | ||
| 440 | return perm && parity % 2 == 0; | 79 | sign = perm_sign(c->ep,12) + perm_sign(c->cp,8) + perm_sign(c->xp,6); |
| 441 | } | ||
| 442 | |||
| 443 | bool | ||
| 444 | is_solved(Cube cube) | ||
| 445 | { | ||
| 446 | return equal(cube, (Cube){0}); | ||
| 447 | } | ||
| 448 | |||
| 449 | bool | ||
| 450 | is_block_solved(Cube cube, Block block) | ||
| 451 | { | ||
| 452 | int i; | ||
| 453 | 80 | ||
| 454 | for (i = 0; i < 12; i++) | 81 | for (i = 0, sum_e = 0; i < 12; i++) |
| 455 | if (block.edge[i] && !is_solved_edge(cube, i)) | 82 | if (c->eo[i] > 1) |
| 456 | return false; | ||
| 457 | for (i = 0; i < 8; i++) | ||
| 458 | if (block.corner[i] && !is_solved_corner(cube, i)) | ||
| 459 | return false; | ||
| 460 | for (i = 0; i < 6; i++) | ||
| 461 | if (block.center[i] && !is_solved_center(cube, i)) | ||
| 462 | return false; | 83 | return false; |
| 84 | else | ||
| 85 | sum_e += c->eo[i]; | ||
| 463 | 86 | ||
| 464 | return true; | 87 | for (i = 0, sum_c = 0; i < 8; i++) |
| 465 | } | 88 | if (c->co[i] > 2) |
| 89 | return false; | ||
| 90 | else | ||
| 91 | sum_c += c->co[i]; | ||
| 466 | 92 | ||
| 467 | bool | 93 | return (perm && sign % 2 == 0 && sum_e % 2 == 0 && sum_c % 2 == 0); |
| 468 | is_solved_center(Cube cube, Center c) | ||
| 469 | { | ||
| 470 | return what_center_at(cube, c) == c; | ||
| 471 | } | 94 | } |
| 472 | 95 | ||
| 473 | bool | 96 | bool |
| 474 | is_solved_corner(Cube cube, Corner c) | 97 | is_solved(Cube *cube) |
| 475 | { | 98 | { |
| 476 | return what_corner_at(cube, c) == c && | 99 | Cube solved_cube; |
| 477 | what_orientation_corner(cube.coud, c); | 100 | make_solved(&solved_cube); |
| 478 | } | ||
| 479 | 101 | ||
| 480 | bool | 102 | return equal(cube, &solved_cube); |
| 481 | is_solved_edge(Cube cube, Edge e) | ||
| 482 | { | ||
| 483 | return what_edge_at(cube, e) == e && | ||
| 484 | what_orientation_edge(cube.eofb, e); | ||
| 485 | } | 103 | } |
| 486 | 104 | ||
| 487 | int | 105 | void |
| 488 | piece_orientation(Cube cube, int piece, char *orientation) | 106 | make_solved(Cube *cube) |
| 489 | { | 107 | { |
| 490 | int arr[12], n, b, x; | 108 | static int sorted[12] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; |
| 491 | 109 | ||
| 492 | if (!strcmp(orientation, "eofb")) { | 110 | memcpy(cube->ep, sorted, 12 * sizeof(int)); |
| 493 | x = cube.eofb; | 111 | memset(cube->eo, 0, 12 * sizeof(int)); |
| 494 | n = 12; | 112 | memcpy(cube->cp, sorted, 8 * sizeof(int)); |
| 495 | b = 2; | 113 | memset(cube->co, 0, 8 * sizeof(int)); |
| 496 | } else if (!strcmp(orientation, "eorl")) { | 114 | memcpy(cube->xp, sorted, 6 * sizeof(int)); |
| 497 | x = cube.eorl; | ||
| 498 | n = 12; | ||
| 499 | b = 2; | ||
| 500 | } else if (!strcmp(orientation, "eoud")) { | ||
| 501 | x = cube.eoud; | ||
| 502 | n = 12; | ||
| 503 | b = 2; | ||
| 504 | } else if (!strcmp(orientation, "coud")) { | ||
| 505 | x = cube.coud; | ||
| 506 | n = 8; | ||
| 507 | b = 3; | ||
| 508 | } else if (!strcmp(orientation, "corl")) { | ||
| 509 | x = cube.corl; | ||
| 510 | n = 8; | ||
| 511 | b = 3; | ||
| 512 | } else if (!strcmp(orientation, "cofb")) { | ||
| 513 | x = cube.cofb; | ||
| 514 | n = 8; | ||
| 515 | b = 3; | ||
| 516 | } else { | ||
| 517 | return -1; | ||
| 518 | } | ||
| 519 | |||
| 520 | int_to_sum_zero_array(x, b, n, arr); | ||
| 521 | if (piece < n) | ||
| 522 | return arr[piece]; | ||
| 523 | |||
| 524 | return -1; | ||
| 525 | } | 115 | } |
| 526 | 116 | ||
| 527 | void | 117 | void |
| 528 | print_cube(Cube cube) | 118 | print_cube(Cube *cube) |
| 529 | { | 119 | { |
| 530 | static char edge_string[12][7] = { | 120 | static char edge_string[12][7] = { |
| 531 | [UF] = "UF", [UL] = "UL", [UB] = "UB", [UR] = "UR", | 121 | [UF] = "UF", [UL] = "UL", [UB] = "UB", [UR] = "UR", |
| @@ -545,388 +135,22 @@ print_cube(Cube cube) | |||
| 545 | }; | 135 | }; |
| 546 | 136 | ||
| 547 | for (int i = 0; i < 12; i++) | 137 | for (int i = 0; i < 12; i++) |
| 548 | printf(" %s ", edge_string[what_edge_at(cube, i)]); | 138 | printf(" %s ", edge_string[cube->ep[i]]); |
| 549 | printf("\n"); | 139 | printf("\n"); |
| 550 | 140 | ||
| 551 | for (int i = 0; i < 12; i++) | 141 | for (int i = 0; i < 12; i++) |
| 552 | printf(" %d ", what_orientation_edge(cube.eofb, i)); | 142 | printf(" %" PRIu8 " ", cube->eo[i]); |
| 553 | printf("\n"); | 143 | printf("\n"); |
| 554 | 144 | ||
| 555 | for (int i = 0; i < 8; i++) | 145 | for (int i = 0; i < 8; i++) |
| 556 | printf("%s ", corner_string[what_corner_at(cube, i)]); | 146 | printf("%s ", corner_string[cube->cp[i]]); |
| 557 | printf("\n"); | 147 | printf("\n"); |
| 558 | 148 | ||
| 559 | for (int i = 0; i < 8; i++) | 149 | for (int i = 0; i < 8; i++) |
| 560 | printf(" %d ", what_orientation_corner(cube.coud, i)); | 150 | printf(" %" PRIu8 " ", cube->co[i]); |
| 561 | printf("\n"); | 151 | printf("\n"); |
| 562 | 152 | ||
| 563 | for (int i = 0; i < 6; i++) | 153 | for (int i = 0; i < 6; i++) |
| 564 | printf(" %s ", center_string[what_center_at(cube, i)]); | 154 | printf(" %s ", center_string[cube->xp[i]]); |
| 565 | printf("\n"); | 155 | printf("\n"); |
| 566 | } | 156 | } |
| 567 | |||
| 568 | Center | ||
| 569 | what_center_at(Cube cube, Center c) | ||
| 570 | { | ||
| 571 | static bool initialized = false; | ||
| 572 | static Center aux[FACTORIAL6][6]; | ||
| 573 | static int i; | ||
| 574 | static unsigned int ui; | ||
| 575 | static CubeArray *arr; | ||
| 576 | |||
| 577 | if (!initialized) { | ||
| 578 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 579 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 580 | for (i = 0; i < 6; i++) | ||
| 581 | aux[ui][i] = arr->cpos[i]; | ||
| 582 | free_cubearray(arr, pf_cpos); | ||
| 583 | } | ||
| 584 | |||
| 585 | initialized = true; | ||
| 586 | } | ||
| 587 | |||
| 588 | return aux[cube.cpos][c]; | ||
| 589 | } | ||
| 590 | |||
| 591 | Corner | ||
| 592 | what_corner_at(Cube cube, Corner c) | ||
| 593 | { | ||
| 594 | int i; | ||
| 595 | unsigned int ui; | ||
| 596 | CubeArray *arr; | ||
| 597 | |||
| 598 | static bool initialized = false; | ||
| 599 | static Corner aux[FACTORIAL8][8]; | ||
| 600 | |||
| 601 | if (!initialized) { | ||
| 602 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 603 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 604 | for (i = 0; i < 8; i++) | ||
| 605 | aux[ui][i] = arr->cp[i]; | ||
| 606 | free_cubearray(arr, pf_cp); | ||
| 607 | } | ||
| 608 | |||
| 609 | initialized = true; | ||
| 610 | } | ||
| 611 | |||
| 612 | return aux[cube.cp][c]; | ||
| 613 | } | ||
| 614 | |||
| 615 | Edge | ||
| 616 | what_edge_at(Cube cube, Edge e) | ||
| 617 | { | ||
| 618 | Edge ret; | ||
| 619 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 620 | |||
| 621 | ret = arr->ep[e]; | ||
| 622 | |||
| 623 | free_cubearray(arr, pf_ep); | ||
| 624 | return ret; | ||
| 625 | } | ||
| 626 | |||
| 627 | int | ||
| 628 | what_orientation_corner(int co, Corner c) | ||
| 629 | { | ||
| 630 | static bool initialized = false; | ||
| 631 | static int auxlast[POW3TO7]; | ||
| 632 | static int auxarr[8]; | ||
| 633 | static unsigned int ui; | ||
| 634 | |||
| 635 | if (!initialized) { | ||
| 636 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 637 | int_to_sum_zero_array(ui, 3, 8, auxarr); | ||
| 638 | auxlast[ui] = auxarr[7]; | ||
| 639 | } | ||
| 640 | |||
| 641 | initialized = true; | ||
| 642 | } | ||
| 643 | |||
| 644 | if (c < 7) | ||
| 645 | return (co / powint(3, c)) % 3; | ||
| 646 | else | ||
| 647 | return auxlast[co]; | ||
| 648 | } | ||
| 649 | |||
| 650 | int | ||
| 651 | what_orientation_edge(int eo, Edge e) | ||
| 652 | { | ||
| 653 | static bool initialized = false; | ||
| 654 | static int auxlast[POW2TO11]; | ||
| 655 | static int auxarr[12]; | ||
| 656 | static unsigned int ui; | ||
| 657 | |||
| 658 | if (!initialized) { | ||
| 659 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 660 | int_to_sum_zero_array(ui, 2, 12, auxarr); | ||
| 661 | auxlast[ui] = auxarr[11]; | ||
| 662 | } | ||
| 663 | |||
| 664 | initialized = true; | ||
| 665 | } | ||
| 666 | |||
| 667 | if (e < 11) | ||
| 668 | return (eo & (1 << e)) ? 1 : 0; | ||
| 669 | else | ||
| 670 | return auxlast[eo]; | ||
| 671 | } | ||
| 672 | |||
| 673 | Center | ||
| 674 | where_is_center(Cube cube, Center c) | ||
| 675 | { | ||
| 676 | static bool initialized = false; | ||
| 677 | static Center aux[FACTORIAL6][6]; | ||
| 678 | static int i; | ||
| 679 | static unsigned int ui; | ||
| 680 | static CubeArray *arr; | ||
| 681 | |||
| 682 | if (!initialized) { | ||
| 683 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 684 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 685 | for (i = 0; i < 6; i++) | ||
| 686 | aux[ui][arr->cpos[i]] = i; | ||
| 687 | free_cubearray(arr, pf_cpos); | ||
| 688 | } | ||
| 689 | |||
| 690 | initialized = true; | ||
| 691 | } | ||
| 692 | |||
| 693 | return aux[cube.cpos][c]; | ||
| 694 | } | ||
| 695 | |||
| 696 | Corner | ||
| 697 | where_is_corner(Cube cube, Corner c) | ||
| 698 | { | ||
| 699 | static bool initialized = false; | ||
| 700 | static Corner aux[FACTORIAL8][8]; | ||
| 701 | static int i; | ||
| 702 | static unsigned int ui; | ||
| 703 | static CubeArray *arr; | ||
| 704 | |||
| 705 | if (!initialized) { | ||
| 706 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 707 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 708 | for (i = 0; i < 8; i++) | ||
| 709 | aux[ui][arr->cp[i]] = i; | ||
| 710 | free_cubearray(arr, pf_cp); | ||
| 711 | } | ||
| 712 | |||
| 713 | initialized = true; | ||
| 714 | } | ||
| 715 | return aux[cube.cp][c]; | ||
| 716 | } | ||
| 717 | |||
| 718 | Edge | ||
| 719 | where_is_edge(Cube c, Edge e) | ||
| 720 | { | ||
| 721 | int r0, r1, r2; | ||
| 722 | |||
| 723 | static bool initialized = false; | ||
| 724 | static int aux[3][BINOM12ON4*FACTORIAL4][12]; | ||
| 725 | static int i, j; | ||
| 726 | static unsigned int ui; | ||
| 727 | static CubeArray *arr; | ||
| 728 | |||
| 729 | if (!initialized) { | ||
| 730 | for (ui = 0; ui < BINOM12ON4*FACTORIAL4; ui++) { | ||
| 731 | for (i = 0; i < 3; i++) | ||
| 732 | for (j = 0; j < 12; j++) | ||
| 733 | aux[i][ui][j] = -1; | ||
| 734 | |||
| 735 | arr = new_cubearray((Cube){.epose = ui}, pf_e); | ||
| 736 | for (i = 0; i < 12; i++) | ||
| 737 | if (edge_slice(arr->ep[i]) == 0) | ||
| 738 | aux[0][ui][arr->ep[i]] = i; | ||
| 739 | free_cubearray(arr, pf_e); | ||
| 740 | |||
| 741 | arr = new_cubearray((Cube){.eposs = ui}, pf_s); | ||
| 742 | for (i = 0; i < 12; i++) | ||
| 743 | if (edge_slice(arr->ep[i]) == 1) | ||
| 744 | aux[1][ui][arr->ep[i]] = i; | ||
| 745 | free_cubearray(arr, pf_s); | ||
| 746 | |||
| 747 | arr = new_cubearray((Cube){.eposm = ui}, pf_m); | ||
| 748 | for (i = 0; i < 12; i++) | ||
| 749 | if (edge_slice(arr->ep[i]) == 2) | ||
| 750 | aux[2][ui][arr->ep[i]] = i; | ||
| 751 | free_cubearray(arr, pf_m); | ||
| 752 | } | ||
| 753 | |||
| 754 | initialized = true; | ||
| 755 | } | ||
| 756 | |||
| 757 | r0 = aux[0][c.epose][e]; | ||
| 758 | r1 = aux[1][c.eposs][e]; | ||
| 759 | r2 = aux[2][c.eposm][e]; | ||
| 760 | return MAX(r0, MAX(r1, r2)); | ||
| 761 | } | ||
| 762 | |||
| 763 | static bool | ||
| 764 | read_invtables_file() | ||
| 765 | { | ||
| 766 | init_env(); | ||
| 767 | |||
| 768 | FILE *f; | ||
| 769 | char fname[strlen(tabledir)+20]; | ||
| 770 | int b; | ||
| 771 | unsigned int ui, meeo, meco, mecp, mecpos; | ||
| 772 | bool r; | ||
| 773 | |||
| 774 | strcpy(fname, tabledir); | ||
| 775 | strcat(fname, "/invtables"); | ||
| 776 | |||
| 777 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 778 | return false; | ||
| 779 | |||
| 780 | b = sizeof(uint16_t); | ||
| 781 | r = true; | ||
| 782 | meeo = BINOM12ON4*FACTORIAL4; | ||
| 783 | meco = FACTORIAL8; | ||
| 784 | mecp = FACTORIAL8; | ||
| 785 | mecpos = FACTORIAL6; | ||
| 786 | |||
| 787 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 788 | r = r && fread(eo_invtable_e[ui], b, meeo, f) == meeo; | ||
| 789 | r = r && fread(eo_invtable_m[ui], b, meeo, f) == meeo; | ||
| 790 | r = r && fread(eo_invtable_s[ui], b, meeo, f) == meeo; | ||
| 791 | } | ||
| 792 | |||
| 793 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 794 | r = r && fread(co_invtable[ui], b, meco, f) == meco; | ||
| 795 | } | ||
| 796 | |||
| 797 | r = r && fread(cp_invtable, b, mecp, f) == mecp; | ||
| 798 | r = r && fread(cpos_invtable, b, mecpos, f) == mecpos; | ||
| 799 | |||
| 800 | fclose(f); | ||
| 801 | return r; | ||
| 802 | } | ||
| 803 | |||
| 804 | static bool | ||
| 805 | write_invtables_file() | ||
| 806 | { | ||
| 807 | init_env(); | ||
| 808 | |||
| 809 | FILE *f; | ||
| 810 | char fname[strlen(tabledir)+20]; | ||
| 811 | unsigned int ui, meeo, meco, mecp, mecpos; | ||
| 812 | int b; | ||
| 813 | bool r; | ||
| 814 | |||
| 815 | strcpy(fname, tabledir); | ||
| 816 | strcat(fname, "/invtables"); | ||
| 817 | |||
| 818 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 819 | return false; | ||
| 820 | |||
| 821 | b = sizeof(uint16_t); | ||
| 822 | r = true; | ||
| 823 | meeo = BINOM12ON4*FACTORIAL4; | ||
| 824 | meco = FACTORIAL8; | ||
| 825 | mecp = FACTORIAL8; | ||
| 826 | mecpos = FACTORIAL6; | ||
| 827 | |||
| 828 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 829 | r = r && fwrite(eo_invtable_e[ui], b, meeo, f) == meeo; | ||
| 830 | r = r && fwrite(eo_invtable_m[ui], b, meeo, f) == meeo; | ||
| 831 | r = r && fwrite(eo_invtable_s[ui], b, meeo, f) == meeo; | ||
| 832 | } | ||
| 833 | |||
| 834 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 835 | r = r && fwrite(co_invtable[ui], b, meco, f) == meco; | ||
| 836 | } | ||
| 837 | |||
| 838 | r = r && fwrite(cp_invtable, b, mecp, f) == mecp; | ||
| 839 | r = r && fwrite(cpos_invtable, b, mecpos, f) == mecpos; | ||
| 840 | |||
| 841 | fclose(f); | ||
| 842 | return r; | ||
| 843 | } | ||
| 844 | |||
| 845 | void | ||
| 846 | init_inverse() | ||
| 847 | { | ||
| 848 | static bool initialized = false; | ||
| 849 | if (initialized) | ||
| 850 | return; | ||
| 851 | initialized = true; | ||
| 852 | |||
| 853 | if (read_invtables_file()) | ||
| 854 | return; | ||
| 855 | |||
| 856 | fprintf(stderr, "Cannot load invtables, generating it\n"); | ||
| 857 | |||
| 858 | CubeArray *aux, *inv; | ||
| 859 | Cube c; | ||
| 860 | int i, j, eoaux[12], eoinv[12]; | ||
| 861 | unsigned int ui, uj; | ||
| 862 | |||
| 863 | aux = new_cubearray((Cube){0}, pf_all); | ||
| 864 | inv = new_cubearray((Cube){0}, pf_all); | ||
| 865 | |||
| 866 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 867 | int_to_sum_zero_array(ui, 2, 12, eoaux); | ||
| 868 | for (uj = 0; uj < BINOM12ON4*FACTORIAL4; uj++) { | ||
| 869 | for (j = 0; j < 12; j++) | ||
| 870 | eoinv[j] = 0; | ||
| 871 | c = (Cube){.epose = uj, .eposm = 0, .eposs = 0}; | ||
| 872 | eoinv[FR] = eoaux[where_is_edge(c, FR)]; | ||
| 873 | eoinv[FL] = eoaux[where_is_edge(c, FL)]; | ||
| 874 | eoinv[BL] = eoaux[where_is_edge(c, BL)]; | ||
| 875 | eoinv[BR] = eoaux[where_is_edge(c, BR)]; | ||
| 876 | eo_invtable_e[ui][uj] = digit_array_to_int(eoinv,11,2); | ||
| 877 | |||
| 878 | for (j = 0; j < 12; j++) | ||
| 879 | eoinv[j] = 0; | ||
| 880 | c = (Cube){.epose = 0, .eposm = uj, .eposs = 0}; | ||
| 881 | eoinv[UF] = eoaux[where_is_edge(c, UF)]; | ||
| 882 | eoinv[UB] = eoaux[where_is_edge(c, UB)]; | ||
| 883 | eoinv[DF] = eoaux[where_is_edge(c, DF)]; | ||
| 884 | eoinv[DB] = eoaux[where_is_edge(c, DB)]; | ||
| 885 | eo_invtable_m[ui][uj] = digit_array_to_int(eoinv,11,2); | ||
| 886 | |||
| 887 | for (j = 0; j < 12; j++) | ||
| 888 | eoinv[j] = 0; | ||
| 889 | c = (Cube){.epose = 0, .eposm = 0, .eposs = uj}; | ||
| 890 | eoinv[UL] = eoaux[where_is_edge(c, UL)]; | ||
| 891 | eoinv[UR] = eoaux[where_is_edge(c, UR)]; | ||
| 892 | eoinv[DL] = eoaux[where_is_edge(c, DL)]; | ||
| 893 | eoinv[DR] = eoaux[where_is_edge(c, DR)]; | ||
| 894 | eo_invtable_s[ui][uj] = digit_array_to_int(eoinv,11,2); | ||
| 895 | } | ||
| 896 | } | ||
| 897 | |||
| 898 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 899 | cube_to_arrays((Cube){.cp = ui}, aux, pf_cp); | ||
| 900 | for (i = 0; i < 8; i++) | ||
| 901 | inv->cp[aux->cp[i]] = i; | ||
| 902 | cp_invtable[ui] = (uint16_t)arrays_to_cube(inv, pf_cp).cp; | ||
| 903 | |||
| 904 | for (uj = 0; uj < POW3TO7; uj++) { | ||
| 905 | cube_to_arrays((Cube){.coud = uj}, aux, pf_coud); | ||
| 906 | for (i = 0; i < 8; i++) | ||
| 907 | inv->coud[aux->cp[i]] = (3-aux->coud[i])%3; | ||
| 908 | co_invtable[uj][ui] = | ||
| 909 | (uint16_t)arrays_to_cube(inv, pf_coud).coud; | ||
| 910 | } | ||
| 911 | } | ||
| 912 | |||
| 913 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 914 | cube_to_arrays((Cube){.cpos = ui}, aux, pf_cpos); | ||
| 915 | for (i = 0; i < 6; i++) | ||
| 916 | inv->cpos[aux->cpos[i]] = i; | ||
| 917 | cpos_invtable[ui] = | ||
| 918 | (uint16_t)arrays_to_cube(inv, pf_cpos).cpos; | ||
| 919 | } | ||
| 920 | |||
| 921 | free_cubearray(aux, pf_all); | ||
| 922 | free_cubearray(inv, pf_all); | ||
| 923 | |||
| 924 | if (!write_invtables_file()) | ||
| 925 | fprintf(stderr, "Error writing invtables\n"); | ||
| 926 | } | ||
| 927 | |||
| 928 | void | ||
| 929 | init_cube() | ||
| 930 | { | ||
| 931 | init_inverse(); | ||
| 932 | } | ||
| @@ -3,44 +3,18 @@ | |||
| 3 | 3 | ||
| 4 | #include <stdio.h> | 4 | #include <stdio.h> |
| 5 | 5 | ||
| 6 | #include "cubetypes.h" | ||
| 6 | #include "env.h" | 7 | #include "env.h" |
| 7 | #include "pf.h" | ||
| 8 | #include "utils.h" | 8 | #include "utils.h" |
| 9 | 9 | ||
| 10 | Cube admissible_ep(Cube cube, PieceFilter f); | 10 | void compose(Cube *c2, Cube *c1); /* Use c2 as an alg on c1 */ |
| 11 | int array_ep_to_epos(int *ep, int *eps_solved); | 11 | void copy_cube(Cube *src, Cube *dst); |
| 12 | Cube arrays_to_cube(CubeArray *arr, PieceFilter f); | 12 | bool equal(Cube *c1, Cube *c2); |
| 13 | Cube compose(Cube c2, Cube c1); /* Use c2 as an alg on c1 */ | 13 | void invert_cube(Cube *cube); |
| 14 | Cube compose_filtered(Cube c2, Cube c1, PieceFilter f); | 14 | bool is_admissible(Cube *cube); |
| 15 | void cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f); | 15 | bool is_solved(Cube *cube); |
| 16 | int edge_slice(Edge e); /* E=0, S=1, M=2 */ | 16 | void make_solved(Cube *cube); |
| 17 | bool equal(Cube c1, Cube c2); | 17 | void print_cube(Cube *cube); |
| 18 | Cube inverse_cube(Cube cube); | ||
| 19 | bool is_admissible(Cube cube); | ||
| 20 | bool is_solved(Cube cube); | ||
| 21 | bool is_block_solved(Cube cube, Block); | ||
| 22 | bool is_solved_center(Cube cube, Center c); | ||
| 23 | bool is_solved_corner(Cube cube, Corner c); | ||
| 24 | bool is_solved_edge(Cube cube, Edge e); | ||
| 25 | void epos_to_partial_ep(int epos, int *ep, int *ss); | ||
| 26 | void epos_to_compatible_ep(int epos, int *ep, int *ss); | ||
| 27 | void fix_eorleoud(CubeArray *arr); | ||
| 28 | void fix_cofbcorl(CubeArray *arr); | ||
| 29 | Cube fourval_to_cube(int eofb, int ep, int coud, int cp); | ||
| 30 | void free_cubearray(CubeArray *arr, PieceFilter f); | ||
| 31 | Cube move_via_arrays(CubeArray *arr, Cube c, PieceFilter pf); | ||
| 32 | CubeArray * new_cubearray(Cube cube, PieceFilter f); | ||
| 33 | void print_cube(Cube cube); | ||
| 34 | Center what_center_at(Cube cube, Center c); | ||
| 35 | Corner what_corner_at(Cube cube, Corner c); | ||
| 36 | Edge what_edge_at(Cube cube, Edge e); | ||
| 37 | int what_orientation_corner(int co, Corner c); | ||
| 38 | int what_orientation_edge(int eo, Edge e); | ||
| 39 | Center where_is_center(Cube cube, Center c); | ||
| 40 | Corner where_is_corner(Cube cube, Corner c); | ||
| 41 | Edge where_is_edge(Cube cube, Edge e); | ||
| 42 | |||
| 43 | void init_cube(); | ||
| 44 | 18 | ||
| 45 | #endif | 19 | #endif |
| 46 | 20 | ||
diff --git a/src/cubetypes.h b/src/cubetypes.h index ad9c627..cf6b7d5 100644 --- a/src/cubetypes.h +++ b/src/cubetypes.h | |||
| @@ -10,6 +10,8 @@ | |||
| 10 | #define NROTATIONS 24 | 10 | #define NROTATIONS 24 |
| 11 | #define entry_group_t uint8_t /* For pruning tables */ | 11 | #define entry_group_t uint8_t /* For pruning tables */ |
| 12 | 12 | ||
| 13 | #define MAX_N_COORD 6 | ||
| 14 | |||
| 13 | /* Enums *********************************************************************/ | 15 | /* Enums *********************************************************************/ |
| 14 | 16 | ||
| 15 | typedef enum | 17 | typedef enum |
| @@ -28,6 +30,12 @@ corner | |||
| 28 | } Corner; | 30 | } Corner; |
| 29 | 31 | ||
| 30 | typedef enum | 32 | typedef enum |
| 33 | coordtype | ||
| 34 | { | ||
| 35 | COMP_COORD, SYM_COORD, SYMCOMP_COORD | ||
| 36 | } CoordType; | ||
| 37 | |||
| 38 | typedef enum | ||
| 31 | edge | 39 | edge |
| 32 | { | 40 | { |
| 33 | UF, UL, UB, UR, | 41 | UF, UL, UB, UR, |
| @@ -81,28 +89,24 @@ typedef struct command Command; | |||
| 81 | typedef struct commandargs CommandArgs; | 89 | typedef struct commandargs CommandArgs; |
| 82 | typedef struct coordinate Coordinate; | 90 | typedef struct coordinate Coordinate; |
| 83 | typedef struct cube Cube; | 91 | typedef struct cube Cube; |
| 84 | typedef struct cubearray CubeArray; | ||
| 85 | typedef struct dfsarg DfsArg; | 92 | typedef struct dfsarg DfsArg; |
| 86 | typedef struct estimatedata EstimateData; | 93 | typedef struct indexer Indexer; |
| 94 | typedef struct movable Movable; | ||
| 87 | typedef struct moveset Moveset; | 95 | typedef struct moveset Moveset; |
| 88 | typedef struct piecefilter PieceFilter; | 96 | typedef struct pdgendata PDGenData; |
| 89 | typedef struct prunedata PruneData; | 97 | typedef struct prunedata PruneData; |
| 90 | typedef struct solveoptions SolveOptions; | 98 | typedef struct solveoptions SolveOptions; |
| 91 | typedef struct step Step; | 99 | typedef struct step Step; |
| 100 | typedef struct stepalt StepAlt; | ||
| 92 | typedef struct symdata SymData; | 101 | typedef struct symdata SymData; |
| 93 | typedef struct threaddatasolve ThreadDataSolve; | 102 | typedef struct threaddatasolve ThreadDataSolve; |
| 94 | typedef struct threaddatagenpt ThreadDataGenpt; | 103 | typedef struct threaddatagenpt ThreadDataGenpt; |
| 104 | typedef struct transgroup TransGroup; | ||
| 95 | 105 | ||
| 96 | typedef Cube (*AntiIndexer) (uint64_t); | 106 | typedef bool (*Checker) (Cube *); |
| 97 | typedef bool (*Checker) (Cube); | ||
| 98 | typedef uint64_t (*CoordMover) (Move, uint64_t); | ||
| 99 | typedef uint64_t (*CoordTransformer) (Trans, uint64_t); | ||
| 100 | typedef int (*Estimator) (DfsArg *); | ||
| 101 | typedef bool (*Validator) (Alg *); | 107 | typedef bool (*Validator) (Alg *); |
| 102 | typedef void (*Exec) (CommandArgs *); | 108 | typedef void (*Exec) (CommandArgs *); |
| 103 | typedef uint64_t (*Indexer) (Cube); | ||
| 104 | typedef CommandArgs * (*ArgParser) (int, char **); | 109 | typedef CommandArgs * (*ArgParser) (int, char **); |
| 105 | typedef int (*TransDetector) (Cube, Trans *); | ||
| 106 | typedef int (*TransFinder) (uint64_t, Trans *); | 110 | typedef int (*TransFinder) (uint64_t, Trans *); |
| 107 | 111 | ||
| 108 | 112 | ||
| @@ -167,83 +171,69 @@ commandargs | |||
| 167 | struct | 171 | struct |
| 168 | coordinate | 172 | coordinate |
| 169 | { | 173 | { |
| 170 | Indexer index; | 174 | char * name; |
| 175 | CoordType type; | ||
| 176 | bool generated; | ||
| 177 | Indexer * i[99]; | ||
| 171 | uint64_t max; | 178 | uint64_t max; |
| 172 | CoordMover move; | 179 | uint64_t * mtable[NMOVES]; |
| 173 | CoordTransformer transform; | 180 | uint64_t * ttable[NTRANS]; |
| 174 | SymData * sd; | 181 | TransGroup * tgrp; |
| 175 | TransFinder tfind; /* TODO: should be easy to remove */ | 182 | Coordinate * base[2]; |
| 176 | Coordinate * base; /* TODO: part of refactor */ | 183 | uint64_t * symclass; |
| 184 | uint64_t * symrep; | ||
| 185 | Trans * transtorep; | ||
| 186 | Trans * ttrep_move[NMOVES]; | ||
| 187 | uint64_t * selfsim; | ||
| 177 | }; | 188 | }; |
| 178 | 189 | ||
| 179 | struct | 190 | struct |
| 180 | cube | 191 | cube |
| 181 | { | 192 | { |
| 182 | int epose; | 193 | int ep[12]; |
| 183 | int eposs; | 194 | int eo[12]; |
| 184 | int eposm; | 195 | int cp[8]; |
| 185 | int eofb; | 196 | int co[8]; |
| 186 | int eorl; | 197 | int xp[6]; |
| 187 | int eoud; | ||
| 188 | int cp; | ||
| 189 | int coud; | ||
| 190 | int cofb; | ||
| 191 | int corl; | ||
| 192 | int cpos; | ||
| 193 | }; | 198 | }; |
| 194 | 199 | ||
| 195 | struct | 200 | struct |
| 196 | cubearray | 201 | movable |
| 197 | { | 202 | { |
| 198 | int * ep; | 203 | uint64_t val; |
| 199 | int * eofb; | 204 | Trans t; |
| 200 | int * eorl; | ||
| 201 | int * eoud; | ||
| 202 | int * cp; | ||
| 203 | int * coud; | ||
| 204 | int * corl; | ||
| 205 | int * cofb; | ||
| 206 | int * cpos; | ||
| 207 | }; | 205 | }; |
| 208 | 206 | ||
| 209 | struct | 207 | struct |
| 210 | dfsarg | 208 | dfsarg |
| 211 | { | 209 | { |
| 212 | Step * step; | 210 | Cube * cube; |
| 213 | SolveOptions * opts; | 211 | Movable ind[MAX_N_COORD]; |
| 214 | Trans t; | 212 | Trans t; |
| 215 | Cube cube; | 213 | StepAlt * sa; |
| 216 | Cube inverse; | 214 | SolveOptions * opts; |
| 217 | int d; | 215 | int d; |
| 218 | uint64_t badmoves; | 216 | int bound; |
| 219 | uint64_t badmovesinv; | ||
| 220 | bool niss; | 217 | bool niss; |
| 221 | Move last1; | 218 | Move last[2]; |
| 222 | Move last2; | 219 | Move lastinv[2]; |
| 223 | Move last1inv; | ||
| 224 | Move last2inv; | ||
| 225 | EstimateData * ed; | ||
| 226 | AlgList * sols; | 220 | AlgList * sols; |
| 227 | pthread_mutex_t * sols_mutex; | 221 | pthread_mutex_t * sols_mutex; |
| 228 | Alg * current_alg; | 222 | Alg * current_alg; |
| 229 | }; | 223 | }; |
| 230 | 224 | ||
| 231 | struct | 225 | struct |
| 232 | estimatedata | 226 | indexer |
| 233 | { | 227 | { |
| 234 | int corners; | 228 | int n; |
| 235 | int normal_ud; | 229 | uint64_t (*index)(Cube *); |
| 236 | int normal_fb; | 230 | void (*to_cube)(uint64_t, Cube *); |
| 237 | int normal_rl; | ||
| 238 | int inverse_ud; | ||
| 239 | int inverse_fb; | ||
| 240 | int inverse_rl; | ||
| 241 | int oldret; | ||
| 242 | }; | 231 | }; |
| 243 | 232 | ||
| 244 | struct | 233 | struct |
| 245 | moveset | 234 | moveset |
| 246 | { | 235 | { |
| 236 | char * name; | ||
| 247 | bool (*allowed)(Move); | 237 | bool (*allowed)(Move); |
| 248 | bool (*allowed_next)(Move, Move, Move); | 238 | bool (*allowed_next)(Move, Move, Move); |
| 249 | Move sorted_moves[NMOVES+1]; | 239 | Move sorted_moves[NMOVES+1]; |
| @@ -251,34 +241,24 @@ moveset | |||
| 251 | }; | 241 | }; |
| 252 | 242 | ||
| 253 | struct | 243 | struct |
| 254 | piecefilter | 244 | pdgendata |
| 255 | { | 245 | { |
| 256 | bool epose; | 246 | Coordinate * coord; |
| 257 | bool eposs; | 247 | Moveset * moveset; |
| 258 | bool eposm; | 248 | bool compact; |
| 259 | bool eofb; | 249 | PruneData * pd; |
| 260 | bool eorl; | ||
| 261 | bool eoud; | ||
| 262 | bool cp; | ||
| 263 | bool coud; | ||
| 264 | bool cofb; | ||
| 265 | bool corl; | ||
| 266 | bool cpos; | ||
| 267 | }; | 250 | }; |
| 268 | 251 | ||
| 269 | struct | 252 | struct |
| 270 | prunedata | 253 | prunedata |
| 271 | { | 254 | { |
| 272 | char * filename; | ||
| 273 | entry_group_t * ptable; | 255 | entry_group_t * ptable; |
| 274 | bool generated; | ||
| 275 | uint64_t n; | 256 | uint64_t n; |
| 276 | Coordinate * coord; | 257 | Coordinate * coord; |
| 277 | Moveset * moveset; | 258 | Moveset * moveset; |
| 278 | bool compact; | 259 | bool compact; |
| 279 | int base; | 260 | int base; |
| 280 | uint64_t count[16]; | 261 | uint64_t count[16]; |
| 281 | PruneData * fallback; | ||
| 282 | uint64_t fbmod; | 262 | uint64_t fbmod; |
| 283 | }; | 263 | }; |
| 284 | 264 | ||
| @@ -302,19 +282,35 @@ step | |||
| 302 | { | 282 | { |
| 303 | char * shortname; | 283 | char * shortname; |
| 304 | char * name; | 284 | char * name; |
| 305 | bool final; | 285 | StepAlt * alt[99]; |
| 306 | Checker is_done; | 286 | Trans t[99]; |
| 307 | Estimator estimate; | ||
| 308 | Checker ready; | ||
| 309 | char * ready_msg; | 287 | char * ready_msg; |
| 310 | Validator is_valid; | 288 | }; |
| 289 | |||
| 290 | struct | ||
| 291 | stepalt | ||
| 292 | { | ||
| 293 | Checker ready; | ||
| 294 | bool final; | ||
| 311 | Moveset * moveset; | 295 | Moveset * moveset; |
| 312 | Trans pre_trans; | 296 | /* Just a comment, (TODO: remove this): moveset is really a stepalt |
| 313 | TransDetector detect; | 297 | * property, because for example we may want to define a "fingertrick |
| 314 | int ntables; | 298 | * friendly ZBLL" step, where we allow either <R U D> or <R U F> as |
| 315 | PruneData * tables[10]; | 299 | * movesets (or similar) */ |
| 300 | int n_coord; | ||
| 301 | Coordinate * coord[MAX_N_COORD]; | ||
| 302 | Trans coord_trans[MAX_N_COORD]; | ||
| 303 | PruneData * pd[MAX_N_COORD]; | ||
| 304 | bool compact_pd[MAX_N_COORD]; | ||
| 305 | Coordinate * fallback_coord[MAX_N_COORD]; | ||
| 306 | PruneData * fallback_pd[MAX_N_COORD]; | ||
| 307 | uint64_t fbmod[MAX_N_COORD]; | ||
| 308 | int n_dbtrick; | ||
| 309 | int dbtrick[MAX_N_COORD][3]; | ||
| 310 | Validator is_valid; | ||
| 316 | }; | 311 | }; |
| 317 | 312 | ||
| 313 | /* | ||
| 318 | struct | 314 | struct |
| 319 | symdata | 315 | symdata |
| 320 | { | 316 | { |
| @@ -328,23 +324,18 @@ symdata | |||
| 328 | uint64_t * unsym; | 324 | uint64_t * unsym; |
| 329 | Trans * transtorep; | 325 | Trans * transtorep; |
| 330 | uint64_t * selfsim; | 326 | uint64_t * selfsim; |
| 331 | CoordTransformer transform; /* TODO: remove, use that of base coord */ | ||
| 332 | }; | 327 | }; |
| 328 | */ | ||
| 329 | |||
| 333 | 330 | ||
| 334 | struct | 331 | struct |
| 335 | threaddatasolve | 332 | threaddatasolve |
| 336 | { | 333 | { |
| 334 | DfsArg arg; | ||
| 337 | int thid; | 335 | int thid; |
| 338 | Trans t; | ||
| 339 | Cube cube; | ||
| 340 | Step * step; | ||
| 341 | int depth; | ||
| 342 | SolveOptions * opts; | ||
| 343 | AlgList * start; | 336 | AlgList * start; |
| 344 | AlgListNode ** node; | 337 | AlgListNode ** node; |
| 345 | AlgList * sols; | ||
| 346 | pthread_mutex_t * start_mutex; | 338 | pthread_mutex_t * start_mutex; |
| 347 | pthread_mutex_t * sols_mutex; | ||
| 348 | }; | 339 | }; |
| 349 | 340 | ||
| 350 | struct | 341 | struct |
| @@ -359,4 +350,11 @@ threaddatagenpt | |||
| 359 | pthread_mutex_t * upmutex; | 350 | pthread_mutex_t * upmutex; |
| 360 | }; | 351 | }; |
| 361 | 352 | ||
| 353 | struct | ||
| 354 | transgroup | ||
| 355 | { | ||
| 356 | int n; | ||
| 357 | Trans t[NTRANS]; | ||
| 358 | }; | ||
| 359 | |||
| 362 | #endif | 360 | #endif |
| @@ -1,3 +1,5 @@ | |||
| 1 | #define ENV_C | ||
| 2 | |||
| 1 | #include "env.h" | 3 | #include "env.h" |
| 2 | 4 | ||
| 3 | bool initialized_env = false; | 5 | bool initialized_env = false; |
| @@ -8,8 +8,8 @@ | |||
| 8 | #include <unistd.h> | 8 | #include <unistd.h> |
| 9 | #include <sys/stat.h> | 9 | #include <sys/stat.h> |
| 10 | 10 | ||
| 11 | extern char *tabledir; | ||
| 12 | |||
| 13 | void init_env(); | 11 | void init_env(); |
| 14 | 12 | ||
| 13 | extern char *tabledir; | ||
| 14 | |||
| 15 | #endif | 15 | #endif |
diff --git a/src/moves.c b/src/moves.c index 02880ca..51012db 100644 --- a/src/moves.c +++ b/src/moves.c | |||
| @@ -1,79 +1,18 @@ | |||
| 1 | #define MOVES_C | ||
| 2 | |||
| 1 | #include "moves.h" | 3 | #include "moves.h" |
| 2 | 4 | ||
| 3 | /* Local functions ***********************************************************/ | 5 | /* Local functions ***********************************************************/ |
| 4 | 6 | ||
| 5 | static Cube apply_move_cubearray(Move m, Cube cube, PieceFilter f); | ||
| 6 | static void cleanup_aux(Alg *alg, Alg *ret, bool inv); | 7 | static void cleanup_aux(Alg *alg, Alg *ret, bool inv); |
| 7 | static bool read_mtables_file(); | ||
| 8 | static bool write_mtables_file(); | ||
| 9 | 8 | ||
| 10 | /* Tables and other data *****************************************************/ | 9 | /* Tables and other data *****************************************************/ |
| 11 | 10 | ||
| 12 | /* Every move is translated to a an <U, x, y> alg before filling the | 11 | /* Moves are represented as cubes and applied using compose(). Every move is * |
| 13 | transition tables, see init_moves() */ | 12 | * translated to a an <U, x, y> alg before filling the transition tables. * |
| 14 | 13 | * See init_moves(). */ | |
| 15 | static int edge_cycle[NMOVES][12] = | ||
| 16 | { | ||
| 17 | [U] = { UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR }, | ||
| 18 | [x] = { DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR }, | ||
| 19 | [y] = { UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL } | ||
| 20 | }; | ||
| 21 | |||
| 22 | static int corner_cycle[NMOVES][8] = | ||
| 23 | { | ||
| 24 | [U] = { UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR }, | ||
| 25 | [x] = { DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR }, | ||
| 26 | [y] = { UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL } | ||
| 27 | }; | ||
| 28 | |||
| 29 | static int center_cycle[NMOVES][6] = | ||
| 30 | { | ||
| 31 | [x] = { F_center, B_center, R_center, L_center, D_center, U_center }, | ||
| 32 | [y] = { U_center, D_center, B_center, F_center, R_center, L_center } | ||
| 33 | }; | ||
| 34 | |||
| 35 | static int eofb_flipped[NMOVES][12] = { | ||
| 36 | [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 37 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } | ||
| 38 | }; | ||
| 39 | 14 | ||
| 40 | static int eorl_flipped[NMOVES][12] = { | 15 | static Cube move_array[NMOVES]; |
| 41 | [x] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, | ||
| 42 | [y] = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 } | ||
| 43 | }; | ||
| 44 | |||
| 45 | static int eoud_flipped[NMOVES][12] = { | ||
| 46 | [U] = { [UF] = 1, [UL] = 1, [UB] = 1, [UR] = 1 }, | ||
| 47 | [x] = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, | ||
| 48 | [y] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } | ||
| 49 | }; | ||
| 50 | |||
| 51 | static int coud_flipped[NMOVES][8] = { | ||
| 52 | [x] = { | ||
| 53 | [UFR] = 2, [UBR] = 1, [UFL] = 1, [UBL] = 2, | ||
| 54 | [DBR] = 2, [DFR] = 1, [DBL] = 1, [DFL] = 2 | ||
| 55 | } | ||
| 56 | }; | ||
| 57 | |||
| 58 | static int corl_flipped[NMOVES][8] = { | ||
| 59 | [U] = { [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2 }, | ||
| 60 | [y] = { | ||
| 61 | [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2, | ||
| 62 | [DFR] = 2, [DBR] = 1, [DBL] = 2, [DFL] = 1 | ||
| 63 | } | ||
| 64 | }; | ||
| 65 | |||
| 66 | static int cofb_flipped[NMOVES][8] = { | ||
| 67 | [U] = { [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1 }, | ||
| 68 | [x] = { | ||
| 69 | [UFR] = 1, [UBR] = 2, [UBL] = 1, [UFL] = 2, | ||
| 70 | [DFR] = 2, [DBR] = 1, [DBL] = 2, [DFL] = 1 | ||
| 71 | }, | ||
| 72 | [y] = { | ||
| 73 | [UFR] = 2, [UBR] = 1, [UBL] = 2, [UFL] = 1, | ||
| 74 | [DFR] = 1, [DBR] = 2, [DBL] = 1, [DFL] = 2 | ||
| 75 | } | ||
| 76 | }; | ||
| 77 | 16 | ||
| 78 | static char equiv_alg_string[100][NMOVES] = { | 17 | static char equiv_alg_string[100][NMOVES] = { |
| 79 | [NULLMOVE] = "", | 18 | [NULLMOVE] = "", |
| @@ -137,89 +76,34 @@ static char equiv_alg_string[100][NMOVES] = { | |||
| 137 | [z3] = " y x yyy " | 76 | [z3] = " y x yyy " |
| 138 | }; | 77 | }; |
| 139 | 78 | ||
| 140 | /* Transition tables, to be loaded up at the beginning */ | ||
| 141 | int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 142 | int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 143 | int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 144 | int eofb_mtable[NMOVES][POW2TO11]; | ||
| 145 | int eorl_mtable[NMOVES][POW2TO11]; | ||
| 146 | int eoud_mtable[NMOVES][POW2TO11]; | ||
| 147 | int cp_mtable[NMOVES][FACTORIAL8]; | ||
| 148 | int coud_mtable[NMOVES][POW3TO7]; | ||
| 149 | int cofb_mtable[NMOVES][POW3TO7]; | ||
| 150 | int corl_mtable[NMOVES][POW3TO7]; | ||
| 151 | int cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 152 | |||
| 153 | |||
| 154 | /* Local functions implementation ********************************************/ | ||
| 155 | |||
| 156 | static Cube | ||
| 157 | apply_move_cubearray(Move m, Cube cube, PieceFilter f) | ||
| 158 | { | ||
| 159 | /*init_moves();*/ | ||
| 160 | |||
| 161 | CubeArray m_arr = { | ||
| 162 | edge_cycle[m], | ||
| 163 | eofb_flipped[m], | ||
| 164 | eorl_flipped[m], | ||
| 165 | eoud_flipped[m], | ||
| 166 | corner_cycle[m], | ||
| 167 | coud_flipped[m], | ||
| 168 | corl_flipped[m], | ||
| 169 | cofb_flipped[m], | ||
| 170 | center_cycle[m] | ||
| 171 | }; | ||
| 172 | |||
| 173 | return move_via_arrays(&m_arr, cube, f); | ||
| 174 | } | ||
| 175 | 79 | ||
| 176 | /* Public functions **********************************************************/ | 80 | /* Public functions **********************************************************/ |
| 177 | 81 | ||
| 178 | Cube | 82 | void |
| 179 | apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a) | 83 | apply_alg(Alg *alg, Cube *cube) |
| 180 | { | 84 | { |
| 181 | Cube ret = {0}; | 85 | Cube aux; |
| 182 | int i; | 86 | int i; |
| 183 | 87 | ||
| 88 | copy_cube(cube, &aux); | ||
| 89 | make_solved(cube); | ||
| 90 | |||
| 184 | for (i = 0; i < alg->len; i++) | 91 | for (i = 0; i < alg->len; i++) |
| 185 | if (alg->inv[i]) | 92 | if (alg->inv[i]) |
| 186 | ret = a ? apply_move(alg->move[i], ret) : | 93 | apply_move(alg->move[i], cube); |
| 187 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 188 | 94 | ||
| 189 | ret = compose_filtered(c, inverse_cube(ret), f); | 95 | invert_cube(cube); |
| 96 | compose(&aux, cube); | ||
| 190 | 97 | ||
| 191 | for (i = 0; i < alg->len; i++) | 98 | for (i = 0; i < alg->len; i++) |
| 192 | if (!alg->inv[i]) | 99 | if (!alg->inv[i]) |
| 193 | ret = a ? apply_move(alg->move[i], ret) : | 100 | apply_move(alg->move[i], cube); |
| 194 | apply_move_cubearray(alg->move[i], ret, f); | ||
| 195 | |||
| 196 | return ret; | ||
| 197 | } | 101 | } |
| 198 | 102 | ||
| 199 | Cube | 103 | void |
| 200 | apply_alg(Alg *alg, Cube cube) | 104 | apply_move(Move m, Cube *cube) |
| 201 | { | 105 | { |
| 202 | return apply_alg_generic(alg, cube, pf_all, true); | 106 | compose(&move_array[m], cube); |
| 203 | } | ||
| 204 | |||
| 205 | Cube | ||
| 206 | apply_move(Move m, Cube cube) | ||
| 207 | { | ||
| 208 | /*init_moves();*/ | ||
| 209 | |||
| 210 | return (Cube) { | ||
| 211 | .epose = epose_mtable[m][cube.epose], | ||
| 212 | .eposs = eposs_mtable[m][cube.eposs], | ||
| 213 | .eposm = eposm_mtable[m][cube.eposm], | ||
| 214 | .eofb = eofb_mtable[m][cube.eofb], | ||
| 215 | .eorl = eorl_mtable[m][cube.eorl], | ||
| 216 | .eoud = eoud_mtable[m][cube.eoud], | ||
| 217 | .coud = coud_mtable[m][cube.coud], | ||
| 218 | .cofb = cofb_mtable[m][cube.cofb], | ||
| 219 | .corl = corl_mtable[m][cube.corl], | ||
| 220 | .cp = cp_mtable[m][cube.cp], | ||
| 221 | .cpos = cpos_mtable[m][cube.cpos] | ||
| 222 | }; | ||
| 223 | } | 107 | } |
| 224 | 108 | ||
| 225 | Alg * | 109 | Alg * |
| @@ -279,31 +163,27 @@ cleanup_aux(Alg *alg, Alg *ret, bool inv) | |||
| 279 | { | 163 | { |
| 280 | int i, j; | 164 | int i, j; |
| 281 | Cube c, d; | 165 | Cube c, d; |
| 282 | Move m, mm; | 166 | Move m; |
| 283 | Alg *equiv_alg; | 167 | Alg *equiv_alg; |
| 284 | 168 | ||
| 285 | c = (Cube){0}; | 169 | make_solved(&c); |
| 286 | for (i = 0; i < alg->len; i++) { | 170 | for (i = 0; i < alg->len; i++) { |
| 287 | if (alg->inv[i] != inv) | 171 | if (alg->inv[i] != inv) |
| 288 | continue; | 172 | continue; |
| 289 | 173 | ||
| 290 | equiv_alg = new_alg(equiv_alg_string[alg->move[i]]); | 174 | equiv_alg = new_alg(equiv_alg_string[alg->move[i]]); |
| 291 | 175 | ||
| 292 | for (j = 0; j < equiv_alg->len; j++) { | 176 | for (j = 0; j < equiv_alg->len; j++) |
| 293 | m = equiv_alg->move[j]; | 177 | if (equiv_alg->move[j] == U) |
| 294 | if (m == U) { | 178 | append_move(ret, 3 * c.xp[U_center] + 1, inv); |
| 295 | mm = 3*what_center_at(c, U_center) + 1; | 179 | else |
| 296 | append_move(ret, mm, inv); | 180 | apply_move(equiv_alg->move[j], &c); |
| 297 | } else { | ||
| 298 | c = apply_move(m, c); | ||
| 299 | } | ||
| 300 | } | ||
| 301 | 181 | ||
| 302 | free_alg(equiv_alg); | 182 | free_alg(equiv_alg); |
| 303 | } | 183 | } |
| 304 | 184 | ||
| 305 | m = NULLMOVE; | 185 | m = NULLMOVE; |
| 306 | switch (what_center_at(c, F_center)) { | 186 | switch (c.xp[F_center]) { |
| 307 | case U_center: | 187 | case U_center: |
| 308 | m = x3; | 188 | m = x3; |
| 309 | break; | 189 | break; |
| @@ -317,7 +197,7 @@ cleanup_aux(Alg *alg, Alg *ret, bool inv) | |||
| 317 | m = y3; | 197 | m = y3; |
| 318 | break; | 198 | break; |
| 319 | case B_center: | 199 | case B_center: |
| 320 | if (what_center_at(c, U_center) == U_center) | 200 | if (c.xp[U_center] == U_center) |
| 321 | m = y2; | 201 | m = y2; |
| 322 | else | 202 | else |
| 323 | m = x2; | 203 | m = x2; |
| @@ -325,120 +205,24 @@ cleanup_aux(Alg *alg, Alg *ret, bool inv) | |||
| 325 | default: | 205 | default: |
| 326 | break; | 206 | break; |
| 327 | } | 207 | } |
| 328 | d = apply_move(m, (Cube){0}); | 208 | |
| 209 | make_solved(&d); | ||
| 210 | apply_move(m, &d); | ||
| 329 | if (m != NULLMOVE) | 211 | if (m != NULLMOVE) |
| 330 | append_move(ret, m, inv); | 212 | append_move(ret, m, inv); |
| 331 | 213 | ||
| 332 | m = NULLMOVE; | 214 | m = NULLMOVE; |
| 333 | if (what_center_at(c, U_center) == what_center_at(d, D_center)) { | 215 | if (c.xp[U_center] == d.xp[D_center]) { |
| 334 | m = z2; | 216 | m = z2; |
| 335 | } else if (what_center_at(c, U_center) == what_center_at(d, R_center)) { | 217 | } else if (c.xp[U_center] == d.xp[R_center]) { |
| 336 | m = z3; | 218 | m = z3; |
| 337 | } else if (what_center_at(c, U_center) == what_center_at(d, L_center)) { | 219 | } else if (c.xp[U_center] == d.xp[L_center]) { |
| 338 | m = z; | 220 | m = z; |
| 339 | } | 221 | } |
| 340 | if (m != NULLMOVE) | 222 | if (m != NULLMOVE) |
| 341 | append_move(ret, m, inv); | 223 | append_move(ret, m, inv); |
| 342 | } | 224 | } |
| 343 | 225 | ||
| 344 | static bool | ||
| 345 | read_mtables_file() | ||
| 346 | { | ||
| 347 | init_env(); | ||
| 348 | |||
| 349 | FILE *f; | ||
| 350 | char fname[strlen(tabledir)+20]; | ||
| 351 | int m, b = sizeof(int); | ||
| 352 | bool r = true; | ||
| 353 | |||
| 354 | /* Table sizes, used for reading and writing files */ | ||
| 355 | uint64_t me[11] = { | ||
| 356 | [0] = FACTORIAL12/FACTORIAL8, | ||
| 357 | [1] = FACTORIAL12/FACTORIAL8, | ||
| 358 | [2] = FACTORIAL12/FACTORIAL8, | ||
| 359 | [3] = POW2TO11, | ||
| 360 | [4] = POW2TO11, | ||
| 361 | [5] = POW2TO11, | ||
| 362 | [6] = FACTORIAL8, | ||
| 363 | [7] = POW3TO7, | ||
| 364 | [8] = POW3TO7, | ||
| 365 | [9] = POW3TO7, | ||
| 366 | [10] = FACTORIAL6 | ||
| 367 | }; | ||
| 368 | |||
| 369 | strcpy(fname, tabledir); | ||
| 370 | strcat(fname, "/mtables"); | ||
| 371 | |||
| 372 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 373 | return false; | ||
| 374 | |||
| 375 | for (m = 0; m < NMOVES; m++) { | ||
| 376 | r = r && fread(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 377 | r = r && fread(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 378 | r = r && fread(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 379 | r = r && fread(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 380 | r = r && fread(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 381 | r = r && fread(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 382 | r = r && fread(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 383 | r = r && fread(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 384 | r = r && fread(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 385 | r = r && fread(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 386 | r = r && fread(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 387 | } | ||
| 388 | |||
| 389 | fclose(f); | ||
| 390 | return r; | ||
| 391 | } | ||
| 392 | |||
| 393 | static bool | ||
| 394 | write_mtables_file() | ||
| 395 | { | ||
| 396 | init_env(); | ||
| 397 | |||
| 398 | FILE *f; | ||
| 399 | char fname[strlen(tabledir)+20]; | ||
| 400 | int m, b = sizeof(int); | ||
| 401 | bool r = true; | ||
| 402 | |||
| 403 | /* Table sizes, used for reading and writing files */ | ||
| 404 | uint64_t me[11] = { | ||
| 405 | [0] = FACTORIAL12/FACTORIAL8, | ||
| 406 | [1] = FACTORIAL12/FACTORIAL8, | ||
| 407 | [2] = FACTORIAL12/FACTORIAL8, | ||
| 408 | [3] = POW2TO11, | ||
| 409 | [4] = POW2TO11, | ||
| 410 | [5] = POW2TO11, | ||
| 411 | [6] = FACTORIAL8, | ||
| 412 | [7] = POW3TO7, | ||
| 413 | [8] = POW3TO7, | ||
| 414 | [9] = POW3TO7, | ||
| 415 | [10] = FACTORIAL6 | ||
| 416 | }; | ||
| 417 | |||
| 418 | strcpy(fname, tabledir); | ||
| 419 | strcat(fname, "/mtables"); | ||
| 420 | |||
| 421 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 422 | return false; | ||
| 423 | |||
| 424 | for (m = 0; m < NMOVES; m++) { | ||
| 425 | r = r && fwrite(epose_mtable[m], b, me[0], f) == me[0]; | ||
| 426 | r = r && fwrite(eposs_mtable[m], b, me[1], f) == me[1]; | ||
| 427 | r = r && fwrite(eposm_mtable[m], b, me[2], f) == me[2]; | ||
| 428 | r = r && fwrite(eofb_mtable[m], b, me[3], f) == me[3]; | ||
| 429 | r = r && fwrite(eorl_mtable[m], b, me[4], f) == me[4]; | ||
| 430 | r = r && fwrite(eoud_mtable[m], b, me[5], f) == me[5]; | ||
| 431 | r = r && fwrite(cp_mtable[m], b, me[6], f) == me[6]; | ||
| 432 | r = r && fwrite(coud_mtable[m], b, me[7], f) == me[7]; | ||
| 433 | r = r && fwrite(corl_mtable[m], b, me[8], f) == me[8]; | ||
| 434 | r = r && fwrite(cofb_mtable[m], b, me[9], f) == me[9]; | ||
| 435 | r = r && fwrite(cpos_mtable[m], b, me[10], f) == me[10]; | ||
| 436 | } | ||
| 437 | |||
| 438 | fclose(f); | ||
| 439 | return r; | ||
| 440 | } | ||
| 441 | |||
| 442 | void | 226 | void |
| 443 | init_moves() { | 227 | init_moves() { |
| 444 | static bool initialized = false; | 228 | static bool initialized = false; |
| @@ -446,101 +230,54 @@ init_moves() { | |||
| 446 | return; | 230 | return; |
| 447 | initialized = true; | 231 | initialized = true; |
| 448 | 232 | ||
| 449 | Cube c; | ||
| 450 | CubeArray arrs; | ||
| 451 | int i; | ||
| 452 | unsigned int ui; | ||
| 453 | Move m; | 233 | Move m; |
| 454 | Alg *equiv_alg[NMOVES]; | 234 | Alg *equiv_alg[NMOVES]; |
| 455 | 235 | ||
| 456 | init_cube(); | 236 | static const Cube mcu = { |
| 457 | 237 | .ep = { UR, UF, UL, UB, DF, DL, DB, DR, FR, FL, BL, BR }, | |
| 458 | for (i = 0; i < NMOVES; i++) | 238 | .cp = { UBR, UFR, UFL, UBL, DFR, DFL, DBL, DBR }, |
| 459 | equiv_alg[i] = new_alg(equiv_alg_string[i]); | 239 | }; |
| 460 | 240 | static const Cube mcx = { | |
| 461 | /* Generate all move cycles and flips; I do this regardless */ | 241 | .ep = { DF, FL, UF, FR, DB, BL, UB, BR, DR, DL, UL, UR }, |
| 462 | for (i = 0; i < NMOVES; i++) { | 242 | .eo = { [UF] = 1, [UB] = 1, [DF] = 1, [DB] = 1 }, |
| 463 | if (i == U || i == x || i == y) | 243 | .cp = { DFR, DFL, UFL, UFR, DBR, DBL, UBL, UBR }, |
| 464 | continue; | 244 | .co = { [UFR] = 2, [UBR] = 1, [UFL] = 1, [UBL] = 2, |
| 465 | 245 | [DBR] = 2, [DFR] = 1, [DBL] = 1, [DFL] = 2 }, | |
| 466 | c = apply_alg_generic(equiv_alg[i], (Cube){0}, pf_all, false); | 246 | .xp = { F_center, B_center, R_center, |
| 467 | 247 | L_center, D_center, U_center }, | |
| 468 | arrs = (CubeArray) { | 248 | }; |
| 469 | edge_cycle[i], | 249 | static const Cube mcy = { |
| 470 | eofb_flipped[i], | 250 | .ep = { UR, UF, UL, UB, DR, DF, DL, DB, BR, FR, FL, BL }, |
| 471 | eorl_flipped[i], | 251 | .eo = { [FR] = 1, [FL] = 1, [BL] = 1, [BR] = 1 }, |
| 472 | eoud_flipped[i], | 252 | .cp = { UBR, UFR, UFL, UBL, DBR, DFR, DFL, DBL }, |
| 473 | corner_cycle[i], | 253 | .xp = { U_center, D_center, B_center, |
| 474 | coud_flipped[i], | 254 | F_center, R_center, L_center }, |
| 475 | corl_flipped[i], | 255 | }; |
| 476 | cofb_flipped[i], | ||
| 477 | center_cycle[i] | ||
| 478 | }; | ||
| 479 | cube_to_arrays(c, &arrs, pf_all); | ||
| 480 | } | ||
| 481 | 256 | ||
| 482 | if (read_mtables_file()) | 257 | move_array[U] = mcu; |
| 483 | return; | 258 | move_array[x] = mcx; |
| 259 | move_array[y] = mcy; | ||
| 484 | 260 | ||
| 485 | fprintf(stderr, "Cannot load %s, generating it\n", "mtables"); | 261 | for (m = 0; m < NMOVES; m++) |
| 262 | equiv_alg[m] = new_alg(equiv_alg_string[m]); | ||
| 486 | 263 | ||
| 487 | /* Initialize transition tables */ | ||
| 488 | for (m = 0; m < NMOVES; m++) { | 264 | for (m = 0; m < NMOVES; m++) { |
| 489 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | 265 | switch (m) { |
| 490 | c = (Cube){ .epose = ui }; | 266 | case NULLMOVE: |
| 491 | c = apply_move_cubearray(m, c, pf_e); | 267 | make_solved(&move_array[m]); |
| 492 | epose_mtable[m][ui] = c.epose; | 268 | break; |
| 493 | 269 | case U: | |
| 494 | c = (Cube){ .eposs = ui }; | 270 | case x: |
| 495 | c = apply_move_cubearray(m, c, pf_s); | 271 | case y: |
| 496 | eposs_mtable[m][ui] = c.eposs; | 272 | break; |
| 497 | 273 | default: | |
| 498 | c = (Cube){ .eposm = ui }; | 274 | make_solved(&move_array[m]); |
| 499 | c = apply_move_cubearray(m, c, pf_m); | 275 | apply_alg(equiv_alg[m], &move_array[m]); |
| 500 | eposm_mtable[m][ui] = c.eposm; | 276 | break; |
| 501 | } | ||
| 502 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 503 | c = (Cube){ .eofb = ui }; | ||
| 504 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 505 | eofb_mtable[m][ui] = c.eofb; | ||
| 506 | |||
| 507 | c = (Cube){ .eorl = ui }; | ||
| 508 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 509 | eorl_mtable[m][ui] = c.eorl; | ||
| 510 | |||
| 511 | c = (Cube){ .eoud = ui }; | ||
| 512 | c = apply_move_cubearray(m, c, pf_eo); | ||
| 513 | eoud_mtable[m][ui] = c.eoud; | ||
| 514 | } | ||
| 515 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 516 | c = (Cube){ .coud = ui }; | ||
| 517 | c = apply_move_cubearray(m, c, pf_co); | ||
| 518 | coud_mtable[m][ui] = c.coud; | ||
| 519 | |||
| 520 | c = (Cube){ .corl = ui }; | ||
| 521 | c = apply_move_cubearray(m, c, pf_co); | ||
| 522 | corl_mtable[m][ui] = c.corl; | ||
| 523 | |||
| 524 | c = (Cube){ .cofb = ui }; | ||
| 525 | c = apply_move_cubearray(m, c, pf_co); | ||
| 526 | cofb_mtable[m][ui] = c.cofb; | ||
| 527 | } | ||
| 528 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 529 | c = (Cube){ .cp = ui }; | ||
| 530 | c = apply_move_cubearray(m, c, pf_cp); | ||
| 531 | cp_mtable[m][ui] = c.cp; | ||
| 532 | } | ||
| 533 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 534 | c = (Cube){ .cpos = ui }; | ||
| 535 | c = apply_move_cubearray(m, c, pf_cpos); | ||
| 536 | cpos_mtable[m][ui] = c.cpos; | ||
| 537 | } | 277 | } |
| 538 | } | 278 | } |
| 539 | 279 | ||
| 540 | if (!write_mtables_file()) | 280 | for (m = 0; m < NMOVES; m++) |
| 541 | fprintf(stderr, "Error writing mtables\n"); | 281 | free_alg(equiv_alg[m]); |
| 542 | |||
| 543 | for (i = 0; i < NMOVES; i++) | ||
| 544 | free_alg(equiv_alg[i]); | ||
| 545 | } | 282 | } |
| 546 | 283 | ||
diff --git a/src/moves.h b/src/moves.h index 14ae087..4afe8fb 100644 --- a/src/moves.h +++ b/src/moves.h | |||
| @@ -5,24 +5,8 @@ | |||
| 5 | #include "cube.h" | 5 | #include "cube.h" |
| 6 | #include "env.h" | 6 | #include "env.h" |
| 7 | 7 | ||
| 8 | /* | 8 | void apply_alg(Alg *alg, Cube *cube); |
| 9 | * Tables are exposed to allow for faster moves in some cases. | 9 | void apply_move(Move m, Cube *cube); |
| 10 | */ | ||
| 11 | extern int epose_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 12 | extern int eposs_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 13 | extern int eposm_mtable[NMOVES][FACTORIAL12/FACTORIAL8]; | ||
| 14 | extern int eofb_mtable[NMOVES][POW2TO11]; | ||
| 15 | extern int eorl_mtable[NMOVES][POW2TO11]; | ||
| 16 | extern int eoud_mtable[NMOVES][POW2TO11]; | ||
| 17 | extern int cp_mtable[NMOVES][FACTORIAL8]; | ||
| 18 | extern int coud_mtable[NMOVES][POW3TO7]; | ||
| 19 | extern int cofb_mtable[NMOVES][POW3TO7]; | ||
| 20 | extern int corl_mtable[NMOVES][POW3TO7]; | ||
| 21 | extern int cpos_mtable[NMOVES][FACTORIAL6]; | ||
| 22 | |||
| 23 | Cube apply_alg(Alg *alg, Cube cube); | ||
| 24 | Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); | ||
| 25 | Cube apply_move(Move m, Cube cube); | ||
| 26 | Alg * cleanup(Alg *alg); | 10 | Alg * cleanup(Alg *alg); |
| 27 | 11 | ||
| 28 | void init_moves(); | 12 | void init_moves(); |
diff --git a/src/pf.c b/src/pf.c deleted file mode 100644 index 7d86e4e..0000000 --- a/src/pf.c +++ /dev/null | |||
| @@ -1,95 +0,0 @@ | |||
| 1 | #include "pf.h" | ||
| 2 | |||
| 3 | PieceFilter | ||
| 4 | pf_all = { | ||
| 5 | .epose = true, | ||
| 6 | .eposs = true, | ||
| 7 | .eposm = true, | ||
| 8 | .eofb = true, | ||
| 9 | .eorl = true, | ||
| 10 | .eoud = true, | ||
| 11 | .cp = true, | ||
| 12 | .cofb = true, | ||
| 13 | .corl = true, | ||
| 14 | .coud = true, | ||
| 15 | .cpos = true | ||
| 16 | }; | ||
| 17 | |||
| 18 | PieceFilter | ||
| 19 | pf_4val = { | ||
| 20 | .epose = true, | ||
| 21 | .eposs = true, | ||
| 22 | .eposm = true, | ||
| 23 | .eofb = true, | ||
| 24 | .coud = true, | ||
| 25 | .cp = true | ||
| 26 | }; | ||
| 27 | |||
| 28 | PieceFilter | ||
| 29 | pf_epcp = { | ||
| 30 | .epose = true, | ||
| 31 | .eposs = true, | ||
| 32 | .eposm = true, | ||
| 33 | .cp = true | ||
| 34 | }; | ||
| 35 | |||
| 36 | PieceFilter | ||
| 37 | pf_cpos = { | ||
| 38 | .cpos = true | ||
| 39 | }; | ||
| 40 | |||
| 41 | PieceFilter | ||
| 42 | pf_cp = { | ||
| 43 | .cp = true | ||
| 44 | }; | ||
| 45 | |||
| 46 | PieceFilter | ||
| 47 | pf_ep = { | ||
| 48 | .epose = true, | ||
| 49 | .eposs = true, | ||
| 50 | .eposm = true | ||
| 51 | }; | ||
| 52 | |||
| 53 | PieceFilter | ||
| 54 | pf_e = { | ||
| 55 | .epose = true | ||
| 56 | }; | ||
| 57 | |||
| 58 | PieceFilter | ||
| 59 | pf_s = { | ||
| 60 | .eposs = true | ||
| 61 | }; | ||
| 62 | |||
| 63 | PieceFilter | ||
| 64 | pf_m = { | ||
| 65 | .eposm = true | ||
| 66 | }; | ||
| 67 | |||
| 68 | PieceFilter | ||
| 69 | pf_eo = { | ||
| 70 | .eofb = true, | ||
| 71 | .eorl = true, | ||
| 72 | .eoud = true | ||
| 73 | }; | ||
| 74 | |||
| 75 | PieceFilter | ||
| 76 | pf_co = { | ||
| 77 | .cofb = true, | ||
| 78 | .corl = true, | ||
| 79 | .coud = true | ||
| 80 | }; | ||
| 81 | |||
| 82 | PieceFilter | ||
| 83 | pf_coud = { | ||
| 84 | .coud = true | ||
| 85 | }; | ||
| 86 | |||
| 87 | PieceFilter | ||
| 88 | pf_edges = { | ||
| 89 | .epose = true, | ||
| 90 | .eposs = true, | ||
| 91 | .eposm = true, | ||
| 92 | .eofb = true, | ||
| 93 | .eorl = true, | ||
| 94 | .eoud = true | ||
| 95 | }; | ||
diff --git a/src/pf.h b/src/pf.h deleted file mode 100644 index 0b552dc..0000000 --- a/src/pf.h +++ /dev/null | |||
| @@ -1,20 +0,0 @@ | |||
| 1 | #ifndef PF_H | ||
| 2 | #define PF_H | ||
| 3 | |||
| 4 | #include "cubetypes.h" | ||
| 5 | |||
| 6 | extern PieceFilter pf_all; | ||
| 7 | extern PieceFilter pf_4val; | ||
| 8 | extern PieceFilter pf_epcp; | ||
| 9 | extern PieceFilter pf_cpos; | ||
| 10 | extern PieceFilter pf_cp; | ||
| 11 | extern PieceFilter pf_ep; | ||
| 12 | extern PieceFilter pf_e; | ||
| 13 | extern PieceFilter pf_s; | ||
| 14 | extern PieceFilter pf_m; | ||
| 15 | extern PieceFilter pf_eo; | ||
| 16 | extern PieceFilter pf_co; | ||
| 17 | extern PieceFilter pf_coud; | ||
| 18 | extern PieceFilter pf_edges; | ||
| 19 | |||
| 20 | #endif | ||
diff --git a/src/pruning.c b/src/pruning.c index 1dba949..5be977c 100644 --- a/src/pruning.c +++ b/src/pruning.c | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | #define PRUNING_C | ||
| 2 | |||
| 1 | #include "pruning.h" | 3 | #include "pruning.h" |
| 2 | 4 | ||
| 3 | #define ENTRIES_PER_GROUP (2*sizeof(entry_group_t)) | 5 | #define ENTRIES_PER_GROUP (2*sizeof(entry_group_t)) |
| @@ -10,101 +12,11 @@ static void genptable_fixnasty(PruneData *pd, int d, int nthreads); | |||
| 10 | static void genptable_setbase(PruneData *pd); | 12 | static void genptable_setbase(PruneData *pd); |
| 11 | static void * instance_bfs(void *arg); | 13 | static void * instance_bfs(void *arg); |
| 12 | static void * instance_fixnasty(void *arg); | 14 | static void * instance_fixnasty(void *arg); |
| 13 | static void ptable_update(PruneData *pd, Cube cube, int m); | 15 | static void ptable_update(PruneData *pd, uint64_t ind, int m); |
| 14 | static void ptable_update_index(PruneData *pd, uint64_t ind, int m); | ||
| 15 | static int ptableval_index(PruneData *pd, uint64_t ind); | ||
| 16 | static bool read_ptable_file(PruneData *pd); | 16 | static bool read_ptable_file(PruneData *pd); |
| 17 | static bool write_ptable_file(PruneData *pd); | 17 | static bool write_ptable_file(PruneData *pd); |
| 18 | 18 | ||
| 19 | PruneData | 19 | PDGenData *active_pdg[256]; |
| 20 | pd_eofb_HTM = { | ||
| 21 | .filename = "pt_eofb_HTM", | ||
| 22 | .coord = &coord_eofb, | ||
| 23 | .moveset = &moveset_HTM, | ||
| 24 | }; | ||
| 25 | |||
| 26 | PruneData | ||
| 27 | pd_coud_HTM = { | ||
| 28 | .filename = "pt_coud_HTM", | ||
| 29 | .coord = &coord_coud, | ||
| 30 | .moveset = &moveset_HTM, | ||
| 31 | }; | ||
| 32 | |||
| 33 | PruneData | ||
| 34 | pd_cornershtr_HTM = { | ||
| 35 | .filename = "pt_cornershtr_HTM", | ||
| 36 | .coord = &coord_cornershtr, | ||
| 37 | .moveset = &moveset_HTM, | ||
| 38 | }; | ||
| 39 | |||
| 40 | PruneData | ||
| 41 | pd_corners_HTM = { | ||
| 42 | .filename = "pt_corners_HTM", | ||
| 43 | .coord = &coord_corners, | ||
| 44 | .moveset = &moveset_HTM, | ||
| 45 | }; | ||
| 46 | |||
| 47 | PruneData | ||
| 48 | pd_drud_sym16_HTM = { | ||
| 49 | .filename = "pt_drud_sym16_HTM", | ||
| 50 | .coord = &coord_drud_sym16, | ||
| 51 | .moveset = &moveset_HTM, | ||
| 52 | }; | ||
| 53 | |||
| 54 | PruneData | ||
| 55 | pd_drud_eofb = { | ||
| 56 | .filename = "pt_drud_eofb", | ||
| 57 | .coord = &coord_drud_eofb, | ||
| 58 | .moveset = &moveset_eofb, | ||
| 59 | }; | ||
| 60 | |||
| 61 | PruneData | ||
| 62 | pd_drudfin_noE_sym16_drud = { | ||
| 63 | .filename = "pt_drudfin_noE_sym16_drud", | ||
| 64 | .coord = &coord_drudfin_noE_sym16, | ||
| 65 | .moveset = &moveset_drud, | ||
| 66 | }; | ||
| 67 | |||
| 68 | PruneData | ||
| 69 | pd_htr_drud = { | ||
| 70 | .filename = "pt_htr_drud", | ||
| 71 | .coord = &coord_htr_drud, | ||
| 72 | .moveset = &moveset_drud, | ||
| 73 | }; | ||
| 74 | |||
| 75 | PruneData | ||
| 76 | pd_htrfin_htr = { | ||
| 77 | .filename = "pt_htrfin_htr", | ||
| 78 | .coord = &coord_htrfin, | ||
| 79 | .moveset = &moveset_htr, | ||
| 80 | }; | ||
| 81 | |||
| 82 | PruneData | ||
| 83 | pd_nxopt31_HTM = { | ||
| 84 | .filename = "pt_nxopt31_HTM", | ||
| 85 | .coord = &coord_nxopt31, | ||
| 86 | .moveset = &moveset_HTM, | ||
| 87 | |||
| 88 | .compact = true, | ||
| 89 | .fallback = &pd_drud_sym16_HTM, | ||
| 90 | .fbmod = BINOM8ON4, | ||
| 91 | }; | ||
| 92 | |||
| 93 | PruneData * all_pd[] = { | ||
| 94 | &pd_eofb_HTM, | ||
| 95 | &pd_coud_HTM, | ||
| 96 | &pd_cornershtr_HTM, | ||
| 97 | &pd_corners_HTM, | ||
| 98 | &pd_drud_sym16_HTM, | ||
| 99 | &pd_drud_eofb, | ||
| 100 | &pd_drudfin_noE_sym16_drud, | ||
| 101 | &pd_htr_drud, | ||
| 102 | &pd_htrfin_htr, | ||
| 103 | &pd_nxopt31_HTM, | ||
| 104 | NULL | ||
| 105 | }; | ||
| 106 | |||
| 107 | /* Functions *****************************************************************/ | ||
| 108 | 20 | ||
| 109 | int | 21 | int |
| 110 | findchunk(PruneData *pd, int nchunks, uint64_t i) | 22 | findchunk(PruneData *pd, int nchunks, uint64_t i) |
| @@ -117,39 +29,41 @@ findchunk(PruneData *pd, int nchunks, uint64_t i) | |||
| 117 | return MIN(nchunks-1, (int)(i / chunksize)); | 29 | return MIN(nchunks-1, (int)(i / chunksize)); |
| 118 | } | 30 | } |
| 119 | 31 | ||
| 120 | void | 32 | PruneData * |
| 121 | free_pd(PruneData *pd) | 33 | genptable(PDGenData *pdg, int nthreads) |
| 122 | { | ||
| 123 | if (pd->generated) | ||
| 124 | free(pd->ptable); | ||
| 125 | |||
| 126 | pd->generated = false; | ||
| 127 | } | ||
| 128 | |||
| 129 | void | ||
| 130 | genptable(PruneData *pd, int nthreads) | ||
| 131 | { | 34 | { |
| 132 | bool compact; | 35 | bool compact; |
| 133 | int d, nchunks; | 36 | int d, nchunks, i; |
| 134 | uint64_t oldn, sz; | 37 | uint64_t oldn, sz; |
| 38 | PruneData *pd; | ||
| 135 | 39 | ||
| 136 | if (pd->generated) | 40 | for (i = 0; active_pdg[i] != NULL; i++) { |
| 137 | return; | 41 | pd = active_pdg[i]->pd; |
| 42 | if (pd->coord == pdg->coord && | ||
| 43 | pd->moveset == pdg->moveset && | ||
| 44 | pd->compact == pdg->compact) | ||
| 45 | return pd; | ||
| 46 | } | ||
| 47 | |||
| 48 | pd = malloc(sizeof(PruneData)); | ||
| 49 | pdg->pd = pd; | ||
| 50 | pd->coord = pdg->coord; | ||
| 51 | pd->moveset = pdg->moveset; | ||
| 52 | pd->compact = pdg->compact; | ||
| 138 | 53 | ||
| 139 | /* TODO: check if memory is enough, otherwise maybe exit gracefully? */ | ||
| 140 | sz = ptablesize(pd) * (pd->compact ? 2 : 1); | 54 | sz = ptablesize(pd) * (pd->compact ? 2 : 1); |
| 141 | pd->ptable = malloc(sz * sizeof(entry_group_t)); | 55 | pd->ptable = malloc(sz * sizeof(entry_group_t)); |
| 142 | 56 | ||
| 143 | if (read_ptable_file(pd)) { | 57 | gen_coord(pd->coord); |
| 144 | pd->generated = true; | 58 | |
| 145 | return; | 59 | if (read_ptable_file(pd)) |
| 146 | } | 60 | goto genptable_done; |
| 147 | 61 | ||
| 148 | if (nthreads < 4) { | 62 | if (nthreads < 4) { |
| 149 | fprintf(stderr, | 63 | fprintf(stderr, |
| 150 | "--- Warning ---\n" | 64 | "--- Warning ---\n" |
| 151 | "You are using only %d threads to generate the pruning" | 65 | "You are using only %d threads to generate the pruning" |
| 152 | "tables. This can take a while." | 66 | "tables. This can take a while.\n" |
| 153 | "Unless you did this intentionally, you should re-run" | 67 | "Unless you did this intentionally, you should re-run" |
| 154 | "this command with `-t 4' or more.\n" | 68 | "this command with `-t 4' or more.\n" |
| 155 | "---------------\n\n", nthreads | 69 | "---------------\n\n", nthreads |
| @@ -160,16 +74,16 @@ genptable(PruneData *pd, int nthreads) | |||
| 160 | /* For the first steps we proceed the same way for compact and not */ | 74 | /* For the first steps we proceed the same way for compact and not */ |
| 161 | compact = pd->compact; | 75 | compact = pd->compact; |
| 162 | pd->compact = false; | 76 | pd->compact = false; |
| 163 | pd->generated = true; | ||
| 164 | 77 | ||
| 165 | nchunks = MIN(ptablesize(pd), 100000); | 78 | nchunks = MIN(ptablesize(pd), 100000); |
| 166 | fprintf(stderr, "Cannot load %s, generating it with %d threads\n", | 79 | fprintf(stderr, "Generating pt_%s_%s with %d threads\n", |
| 167 | pd->filename, nthreads); | 80 | pd->coord->name, pd->moveset->name, nthreads); |
| 168 | |||
| 169 | 81 | ||
| 170 | memset(pd->ptable, ~(uint8_t)0, ptablesize(pd)*sizeof(entry_group_t)); | 82 | memset(pd->ptable, ~(uint8_t)0, ptablesize(pd)*sizeof(entry_group_t)); |
| 83 | for (i = 0; i < 16; i++) | ||
| 84 | pd->count[i] = 0; | ||
| 171 | 85 | ||
| 172 | ptable_update(pd, (Cube){0}, 0); | 86 | ptable_update(pd, 0, 0); |
| 173 | pd->n = 1; | 87 | pd->n = 1; |
| 174 | oldn = 0; | 88 | oldn = 0; |
| 175 | genptable_fixnasty(pd, 0, nthreads); | 89 | genptable_fixnasty(pd, 0, nthreads); |
| @@ -192,9 +106,19 @@ genptable(PruneData *pd, int nthreads) | |||
| 192 | genptable_setbase(pd); | 106 | genptable_setbase(pd); |
| 193 | if (compact) | 107 | if (compact) |
| 194 | genptable_compress(pd); | 108 | genptable_compress(pd); |
| 195 | 109 | ||
| 196 | if (!write_ptable_file(pd)) | 110 | if (!write_ptable_file(pd)) |
| 197 | fprintf(stderr, "Error writing ptable file\n"); | 111 | fprintf(stderr, "Error writing ptable file\n"); |
| 112 | |||
| 113 | genptable_done: | ||
| 114 | for (i = 0; active_pdg[i] != NULL; i++); | ||
| 115 | active_pdg[i] = malloc(sizeof(PDGenData)); | ||
| 116 | active_pdg[i]->coord = pdg->coord; | ||
| 117 | active_pdg[i]->moveset = pdg->moveset; | ||
| 118 | active_pdg[i]->compact = pdg->compact; | ||
| 119 | active_pdg[i]->pd = pd; | ||
| 120 | |||
| 121 | return pd; | ||
| 198 | } | 122 | } |
| 199 | 123 | ||
| 200 | static void | 124 | static void |
| @@ -245,7 +169,7 @@ genptable_compress(PruneData *pd) | |||
| 245 | for (j = 0; j < ENTRIES_PER_GROUP_COMPACT; j++) { | 169 | for (j = 0; j < ENTRIES_PER_GROUP_COMPACT; j++) { |
| 246 | if (i+j >= pd->coord->max) | 170 | if (i+j >= pd->coord->max) |
| 247 | break; | 171 | break; |
| 248 | val = ptableval_index(pd, i+j) - pd->base; | 172 | val = ptableval(pd, i+j) - pd->base; |
| 249 | v = (entry_group_t)MIN(3, MAX(0, val)); | 173 | v = (entry_group_t)MIN(3, MAX(0, val)); |
| 250 | mask |= v << (2*j); | 174 | mask |= v << (2*j); |
| 251 | } | 175 | } |
| @@ -264,7 +188,7 @@ genptable_fixnasty(PruneData *pd, int d, int nthreads) | |||
| 264 | ThreadDataGenpt td[nthreads]; | 188 | ThreadDataGenpt td[nthreads]; |
| 265 | pthread_mutex_t *upmtx; | 189 | pthread_mutex_t *upmtx; |
| 266 | 190 | ||
| 267 | if (pd->coord->tfind == NULL) | 191 | if (pd->coord->type != SYMCOMP_COORD) |
| 268 | return; | 192 | return; |
| 269 | 193 | ||
| 270 | upmtx = malloc(sizeof(pthread_mutex_t)); | 194 | upmtx = malloc(sizeof(pthread_mutex_t)); |
| @@ -320,17 +244,17 @@ instance_bfs(void *arg) | |||
| 320 | for (i = rmin; i < rmax; i++) { | 244 | for (i = rmin; i < rmax; i++) { |
| 321 | ichunk = findchunk(td->pd, td->nchunks, i); | 245 | ichunk = findchunk(td->pd, td->nchunks, i); |
| 322 | pthread_mutex_lock(td->mutex[ichunk]); | 246 | pthread_mutex_lock(td->mutex[ichunk]); |
| 323 | pval = ptableval_index(td->pd, i); | 247 | pval = ptableval(td->pd, i); |
| 324 | pthread_mutex_unlock(td->mutex[ichunk]); | 248 | pthread_mutex_unlock(td->mutex[ichunk]); |
| 325 | if (pval == td->d) { | 249 | if (pval == td->d) { |
| 326 | for (j = 0; ms[j] != NULLMOVE; j++) { | 250 | for (j = 0; ms[j] != NULLMOVE; j++) { |
| 327 | ii = td->pd->coord->move(ms[j], i); | 251 | /* ii = td->pd->coord->move(ms[j], i); */ |
| 252 | ii = move_coord(td->pd->coord, ms[j], i, NULL); | ||
| 328 | ichunk = findchunk(td->pd, td->nchunks, ii); | 253 | ichunk = findchunk(td->pd, td->nchunks, ii); |
| 329 | pthread_mutex_lock(td->mutex[ichunk]); | 254 | pthread_mutex_lock(td->mutex[ichunk]); |
| 330 | pval = ptableval_index(td->pd, ii); | 255 | pval = ptableval(td->pd, ii); |
| 331 | if (pval > td->d+1) { | 256 | if (pval > td->d+1) { |
| 332 | ptable_update_index(td->pd, | 257 | ptable_update(td->pd, ii, td->d+1); |
| 333 | ii, td->d+1); | ||
| 334 | updated++; | 258 | updated++; |
| 335 | } | 259 | } |
| 336 | pthread_mutex_unlock(td->mutex[ichunk]); | 260 | pthread_mutex_unlock(td->mutex[ichunk]); |
| @@ -349,13 +273,15 @@ static void * | |||
| 349 | instance_fixnasty(void *arg) | 273 | instance_fixnasty(void *arg) |
| 350 | { | 274 | { |
| 351 | ThreadDataGenpt *td; | 275 | ThreadDataGenpt *td; |
| 352 | uint64_t i, ii, nb, blocksize, rmin, rmax, updated; | 276 | uint64_t i, ii, blocksize, rmin, rmax, updated, ss, M; |
| 353 | int j, n; | 277 | int j; |
| 354 | Trans t, aux[NTRANS]; | 278 | Trans t; |
| 355 | 279 | ||
| 356 | td = (ThreadDataGenpt *)arg; | 280 | td = (ThreadDataGenpt *)arg; |
| 357 | nb = td->pd->coord->max / td->pd->coord->base->max; | 281 | |
| 358 | blocksize = (td->pd->coord->base->max / td->nthreads) * nb; | 282 | /* We know type = SYMCOMP_COORD */ |
| 283 | M = td->pd->coord->base[1]->max; | ||
| 284 | blocksize = (td->pd->coord->base[0]->max / td->nthreads) * M; | ||
| 359 | rmin = ((uint64_t)td->thid) * blocksize; | 285 | rmin = ((uint64_t)td->thid) * blocksize; |
| 360 | rmax = td->thid == td->nthreads - 1 ? | 286 | rmax = td->thid == td->nthreads - 1 ? |
| 361 | td->pd->coord->max : | 287 | td->pd->coord->max : |
| @@ -363,16 +289,15 @@ instance_fixnasty(void *arg) | |||
| 363 | 289 | ||
| 364 | updated = 0; | 290 | updated = 0; |
| 365 | for (i = rmin; i < rmax; i++) { | 291 | for (i = rmin; i < rmax; i++) { |
| 366 | if (ptableval_index(td->pd, i) == td->d) { | 292 | if (ptableval(td->pd, i) == td->d) { |
| 367 | if ((n = td->pd->coord->tfind(i, aux)) == 1) | 293 | ss = td->pd->coord->base[0]->selfsim[i/M]; |
| 368 | continue; | 294 | for (j = 0; j < td->pd->coord->base[0]->tgrp->n; j++) { |
| 369 | 295 | t = td->pd->coord->base[0]->tgrp->t[j]; | |
| 370 | for (j = 0; j < n; j++) { | 296 | if (t == uf || !(ss & ((uint64_t)1<<t))) |
| 371 | if ((t = aux[j]) == uf) | ||
| 372 | continue; | 297 | continue; |
| 373 | ii = td->pd->coord->transform(t, i); | 298 | ii = trans_coord(td->pd->coord, t, i); |
| 374 | if (ptableval_index(td->pd, ii) > td->d) { | 299 | if (ptableval(td->pd, ii) > td->d) { |
| 375 | ptable_update_index(td->pd, ii, td->d); | 300 | ptable_update(td->pd, ii, td->d); |
| 376 | updated++; | 301 | updated++; |
| 377 | } | 302 | } |
| 378 | } | 303 | } |
| @@ -391,10 +316,7 @@ print_ptable(PruneData *pd) | |||
| 391 | { | 316 | { |
| 392 | uint64_t i; | 317 | uint64_t i; |
| 393 | 318 | ||
| 394 | if (!pd->generated) | 319 | printf("Table %s_%s\n", pd->coord->name, pd->moveset->name); |
| 395 | genptable(pd, 1); /* TODO: set default nthreads somewhere */ | ||
| 396 | |||
| 397 | printf("Table %s\n", pd->filename); | ||
| 398 | printf("Base value: %d\n", pd->base); | 320 | printf("Base value: %d\n", pd->base); |
| 399 | for (i = 0; i < 16; i++) | 321 | for (i = 0; i < 16; i++) |
| 400 | printf("%2" PRIu64 "\t%10" PRIu64 "\n", i, pd->count[i]); | 322 | printf("%2" PRIu64 "\t%10" PRIu64 "\n", i, pd->count[i]); |
| @@ -411,13 +333,7 @@ ptablesize(PruneData *pd) | |||
| 411 | } | 333 | } |
| 412 | 334 | ||
| 413 | static void | 335 | static void |
| 414 | ptable_update(PruneData *pd, Cube cube, int n) | 336 | ptable_update(PruneData *pd, uint64_t ind, int n) |
| 415 | { | ||
| 416 | ptable_update_index(pd, pd->coord->index(cube), n); | ||
| 417 | } | ||
| 418 | |||
| 419 | static void | ||
| 420 | ptable_update_index(PruneData *pd, uint64_t ind, int n) | ||
| 421 | { | 337 | { |
| 422 | int sh; | 338 | int sh; |
| 423 | entry_group_t mask; | 339 | entry_group_t mask; |
| @@ -432,27 +348,12 @@ ptable_update_index(PruneData *pd, uint64_t ind, int n) | |||
| 432 | } | 348 | } |
| 433 | 349 | ||
| 434 | int | 350 | int |
| 435 | ptableval(PruneData *pd, Cube cube) | 351 | ptableval(PruneData *pd, uint64_t ind) |
| 436 | { | ||
| 437 | return ptableval_index(pd, pd->coord->index(cube)); | ||
| 438 | } | ||
| 439 | |||
| 440 | static int | ||
| 441 | ptableval_index(PruneData *pd, uint64_t ind) | ||
| 442 | { | 352 | { |
| 443 | int sh, ret; | 353 | int sh, ret; |
| 444 | entry_group_t mask; | 354 | uint64_t e; |
| 445 | uint64_t i, e; | ||
| 446 | entry_group_t m; | 355 | entry_group_t m; |
| 447 | 356 | ||
| 448 | if (!pd->generated) { | ||
| 449 | fprintf(stderr, "Warning: request pruning table value" | ||
| 450 | " for uninitialized table %s.\n It's fine, but it" | ||
| 451 | " should not happen. Please report bug.\n", | ||
| 452 | pd->filename); | ||
| 453 | genptable(pd, 1); /* TODO: set default or remove this case */ | ||
| 454 | } | ||
| 455 | |||
| 456 | if (pd->compact) { | 357 | if (pd->compact) { |
| 457 | e = ENTRIES_PER_GROUP_COMPACT; | 358 | e = ENTRIES_PER_GROUP_COMPACT; |
| 458 | m = 3; | 359 | m = 3; |
| @@ -463,19 +364,9 @@ ptableval_index(PruneData *pd, uint64_t ind) | |||
| 463 | sh = (ind % e) * 4; | 364 | sh = (ind % e) * 4; |
| 464 | } | 365 | } |
| 465 | 366 | ||
| 466 | mask = m << sh; | 367 | ret = (pd->ptable[ind/e] & (m << sh)) >> sh; |
| 467 | i = ind/e; | ||
| 468 | |||
| 469 | ret = (pd->ptable[i] & mask) >> sh; | ||
| 470 | |||
| 471 | if (pd->compact) { | ||
| 472 | if (ret) | ||
| 473 | ret += pd->base; | ||
| 474 | else | ||
| 475 | ret = ptableval_index(pd->fallback, ind / pd->fbmod); | ||
| 476 | } | ||
| 477 | 368 | ||
| 478 | return ret; | 369 | return pd->compact ? ret + pd->base : ret; |
| 479 | } | 370 | } |
| 480 | 371 | ||
| 481 | static bool | 372 | static bool |
| @@ -484,13 +375,15 @@ read_ptable_file(PruneData *pd) | |||
| 484 | init_env(); | 375 | init_env(); |
| 485 | 376 | ||
| 486 | FILE *f; | 377 | FILE *f; |
| 487 | char fname[strlen(tabledir)+100]; | 378 | char fname[strlen(tabledir)+256]; |
| 488 | int i; | 379 | int i; |
| 489 | uint64_t r; | 380 | uint64_t r; |
| 490 | 381 | ||
| 491 | strcpy(fname, tabledir); | 382 | strcpy(fname, tabledir); |
| 492 | strcat(fname, "/"); | 383 | strcat(fname, "/pt_"); |
| 493 | strcat(fname, pd->filename); | 384 | strcat(fname, pd->coord->name); |
| 385 | strcat(fname, "_"); | ||
| 386 | strcat(fname, pd->moveset->name); | ||
| 494 | 387 | ||
| 495 | if ((f = fopen(fname, "rb")) == NULL) | 388 | if ((f = fopen(fname, "rb")) == NULL) |
| 496 | return false; | 389 | return false; |
| @@ -511,13 +404,15 @@ write_ptable_file(PruneData *pd) | |||
| 511 | init_env(); | 404 | init_env(); |
| 512 | 405 | ||
| 513 | FILE *f; | 406 | FILE *f; |
| 514 | char fname[strlen(tabledir)+100]; | 407 | char fname[strlen(tabledir)+256]; |
| 515 | int i; | 408 | int i; |
| 516 | uint64_t w; | 409 | uint64_t w; |
| 517 | 410 | ||
| 518 | strcpy(fname, tabledir); | 411 | strcpy(fname, tabledir); |
| 519 | strcat(fname, "/"); | 412 | strcat(fname, "/pt_"); |
| 520 | strcat(fname, pd->filename); | 413 | strcat(fname, pd->coord->name); |
| 414 | strcat(fname, "_"); | ||
| 415 | strcat(fname, pd->moveset->name); | ||
| 521 | 416 | ||
| 522 | if ((f = fopen(fname, "wb")) == NULL) | 417 | if ((f = fopen(fname, "wb")) == NULL) |
| 523 | return false; | 418 | return false; |
diff --git a/src/pruning.h b/src/pruning.h index 6bdbee1..6965910 100644 --- a/src/pruning.h +++ b/src/pruning.h | |||
| @@ -1,26 +1,15 @@ | |||
| 1 | #ifndef PRUNING_H | 1 | #ifndef PRUNING_H |
| 2 | #define PRUNING_H | 2 | #define PRUNING_H |
| 3 | 3 | ||
| 4 | #include "symcoord.h" | 4 | #include "coord.h" |
| 5 | |||
| 6 | extern PruneData pd_eofb_HTM; | ||
| 7 | extern PruneData pd_coud_HTM; | ||
| 8 | extern PruneData pd_corners_HTM; | ||
| 9 | extern PruneData pd_cornershtr_HTM; | ||
| 10 | extern PruneData pd_drud_sym16_HTM; | ||
| 11 | extern PruneData pd_drud_eofb; | ||
| 12 | extern PruneData pd_drudfin_noE_sym16_drud; | ||
| 13 | extern PruneData pd_htr_drud; | ||
| 14 | extern PruneData pd_htrfin_htr; | ||
| 15 | extern PruneData pd_nxopt31_HTM; | ||
| 16 | |||
| 17 | extern PruneData * all_pd[]; | ||
| 18 | 5 | ||
| 19 | void free_pd(PruneData *pd); | 6 | void free_pd(PruneData *pd); |
| 20 | void genptable(PruneData *pd, int nthreads); | 7 | PruneData * genptable(PDGenData *data, int nthreads); |
| 21 | void print_ptable(PruneData *pd); | 8 | void print_ptable(PruneData *pd); |
| 22 | uint64_t ptablesize(PruneData *pd); | 9 | uint64_t ptablesize(PruneData *pd); |
| 23 | int ptableval(PruneData *pd, Cube cube); | 10 | int ptableval(PruneData *pd, uint64_t ind); |
| 11 | |||
| 12 | extern PDGenData *active_pdg[256]; | ||
| 24 | 13 | ||
| 25 | #endif | 14 | #endif |
| 26 | 15 | ||
diff --git a/src/shell.c b/src/shell.c index 0001e0d..44665a8 100644 --- a/src/shell.c +++ b/src/shell.c | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | #define SHELL_C | ||
| 2 | |||
| 1 | #include "shell.h" | 3 | #include "shell.h" |
| 2 | 4 | ||
| 3 | static void cleanwhitespaces(char *line); | 5 | static void cleanwhitespaces(char *line); |
| @@ -7,7 +9,9 @@ bool | |||
| 7 | checkfiles() | 9 | checkfiles() |
| 8 | { | 10 | { |
| 9 | /* TODO: add more checks (other files, use checksum...) */ | 11 | /* TODO: add more checks (other files, use checksum...) */ |
| 10 | FILE *f; | 12 | /* How to check for pruning tables with new method? */ |
| 13 | /* Solution: use list of steps */ | ||
| 14 | /* | ||
| 11 | char fname[strlen(tabledir)+100]; | 15 | char fname[strlen(tabledir)+100]; |
| 12 | int i; | 16 | int i; |
| 13 | 17 | ||
| @@ -20,6 +24,7 @@ checkfiles() | |||
| 20 | else | 24 | else |
| 21 | fclose(f); | 25 | fclose(f); |
| 22 | } | 26 | } |
| 27 | */ | ||
| 23 | 28 | ||
| 24 | return true; | 29 | return true; |
| 25 | } | 30 | } |
| @@ -143,6 +148,21 @@ main(int argc, char *argv[]) | |||
| 143 | char *closing_cmd[1] = { "freemem" }; | 148 | char *closing_cmd[1] = { "freemem" }; |
| 144 | 149 | ||
| 145 | init_env(); | 150 | init_env(); |
| 151 | init_trans(); | ||
| 152 | |||
| 153 | /* | ||
| 154 | Cube c; | ||
| 155 | make_solved(&c); | ||
| 156 | c.co[0] = 1; | ||
| 157 | c.co[6] = 2; | ||
| 158 | print_cube(&c); | ||
| 159 | apply_trans(uf_mirror, &c); | ||
| 160 | print_cube(&c); | ||
| 161 | */ | ||
| 162 | |||
| 163 | /* | ||
| 164 | test_coord(&coord_coud_cpudsep); | ||
| 165 | */ | ||
| 146 | 166 | ||
| 147 | if (!checkfiles()) { | 167 | if (!checkfiles()) { |
| 148 | fprintf(stderr, | 168 | fprintf(stderr, |
diff --git a/src/solve.c b/src/solve.c index d4c0f18..911d208 100644 --- a/src/solve.c +++ b/src/solve.c | |||
| @@ -1,37 +1,34 @@ | |||
| 1 | #define SOLVE_C | ||
| 2 | |||
| 1 | #include "solve.h" | 3 | #include "solve.h" |
| 2 | 4 | ||
| 3 | /* Local functions ***********************************************************/ | 5 | /* Local functions ***********************************************************/ |
| 4 | 6 | ||
| 5 | static bool allowed_next(Move move, DfsArg *arg); | 7 | static bool allowed_next(Move move, StepAlt *sa, Move l0, Move l1); |
| 6 | static bool cancel_niss(DfsArg *arg); | 8 | static bool cancel_niss(DfsArg *arg); |
| 7 | static void copy_dfsarg(DfsArg *src, DfsArg *dst); | 9 | static void copy_dfsarg(DfsArg *src, DfsArg *dst); |
| 8 | static void dfs(DfsArg *arg); | 10 | static void dfs(DfsArg *arg); |
| 9 | static void dfs_branch(DfsArg *arg); | 11 | static void dfs_add_sol(DfsArg *arg); |
| 10 | static bool dfs_check_solved(DfsArg *arg); | ||
| 11 | static bool dfs_switch(DfsArg *arg); | ||
| 12 | static void dfs_niss(DfsArg *arg); | 12 | static void dfs_niss(DfsArg *arg); |
| 13 | static bool dfs_stop(DfsArg *arg); | 13 | static bool dfs_move_checkstop(DfsArg *arg); |
| 14 | static void * instance_thread(void *arg); | 14 | static void * instance_thread(void *arg); |
| 15 | static void invert_branch(DfsArg *arg); | 15 | static void multidfs(DfsArg *arg); |
| 16 | static void multidfs(Cube c, Trans t, Step *s, SolveOptions *opts, | ||
| 17 | AlgList *sols, int d); | ||
| 18 | static bool niss_makes_sense(DfsArg *arg); | 16 | static bool niss_makes_sense(DfsArg *arg); |
| 19 | static bool solvestop(int d, int op, SolveOptions *opts, AlgList *sols); | 17 | static bool solvestop(int d, int op, SolveOptions *opts, AlgList *sols); |
| 20 | 18 | ||
| 21 | /* Local functions ***********************************************************/ | 19 | /* Local functions ***********************************************************/ |
| 22 | 20 | ||
| 23 | static bool | 21 | static bool |
| 24 | allowed_next(Move m, DfsArg *arg) | 22 | allowed_next(Move m, StepAlt *sa, Move l0, Move l1) |
| 25 | { | 23 | { |
| 26 | bool bad, allowed, order; | 24 | bool allowed, order; |
| 27 | uint64_t mbit; | 25 | uint64_t mbit; |
| 28 | 26 | ||
| 29 | mbit = ((uint64_t)1) << m; | 27 | mbit = ((uint64_t)1) << m; |
| 30 | bad = mbit & arg->badmoves; | 28 | allowed = mbit & sa->moveset->mask[l1][l0]; |
| 31 | allowed = mbit & arg->step->moveset->mask[arg->last2][arg->last1]; | 29 | order = !commute(l0, m) || l0 < m; |
| 32 | order = !commute(arg->last1, m) || arg->last1 < m; | ||
| 33 | 30 | ||
| 34 | return allowed && !bad && order; | 31 | return allowed && order; |
| 35 | } | 32 | } |
| 36 | 33 | ||
| 37 | static bool | 34 | static bool |
| @@ -41,20 +38,20 @@ cancel_niss(DfsArg *arg) | |||
| 41 | Move i1, i2; | 38 | Move i1, i2; |
| 42 | bool p, p1, p2, q, q1, q2; | 39 | bool p, p1, p2, q, q1, q2; |
| 43 | 40 | ||
| 44 | if (arg->last1inv == NULLMOVE) | 41 | if (arg->lastinv[0] == NULLMOVE) |
| 45 | return false; | 42 | return false; |
| 46 | 43 | ||
| 47 | ms = arg->step->moveset; | 44 | ms = arg->sa->moveset; |
| 48 | i1 = inverse_move(arg->last1inv); | 45 | i1 = inverse_move(arg->lastinv[0]); |
| 49 | i2 = inverse_move(arg->last2inv); | 46 | i2 = inverse_move(arg->lastinv[1]); |
| 50 | 47 | ||
| 51 | p1 = !ms->allowed_next(arg->last2, arg->last1, i1); | 48 | p1 = !ms->allowed_next(arg->last[1], arg->last[0], i1); |
| 52 | p2 = !ms->allowed_next(arg->last2, i1, arg->last1); | 49 | p2 = !ms->allowed_next(arg->last[1], i1, arg->last[0]); |
| 53 | p = p1 || (commute(i1, arg->last1) && p2); | 50 | p = p1 || (commute(i1, arg->last[0]) && p2); |
| 54 | 51 | ||
| 55 | q1 = !ms->allowed_next(arg->last2, arg->last1, i2); | 52 | q1 = !ms->allowed_next(arg->last[1], arg->last[0], i2); |
| 56 | q2 = !ms->allowed_next(arg->last2, i2, arg->last1); | 53 | q2 = !ms->allowed_next(arg->last[1], i2, arg->last[0]); |
| 57 | q = q1 || (commute(i2, arg->last1) && q2); | 54 | q = q1 || (commute(i2, arg->last[0]) && q2); |
| 58 | 55 | ||
| 59 | return p || (commute(i1, i2) && q); | 56 | return p || (commute(i1, i2) && q); |
| 60 | } | 57 | } |
| @@ -62,142 +59,145 @@ cancel_niss(DfsArg *arg) | |||
| 62 | static void | 59 | static void |
| 63 | copy_dfsarg(DfsArg *src, DfsArg *dst) | 60 | copy_dfsarg(DfsArg *src, DfsArg *dst) |
| 64 | { | 61 | { |
| 65 | dst->step = src->step; | 62 | int i; |
| 66 | dst->opts = src->opts; | ||
| 67 | dst->t = src->t; | ||
| 68 | dst->cube = src->cube; | ||
| 69 | dst->inverse = src->inverse; | ||
| 70 | dst->d = src->d; | ||
| 71 | dst->badmoves = src->badmoves; | ||
| 72 | dst->badmovesinv = src->badmovesinv; | ||
| 73 | dst->niss = src->niss; | ||
| 74 | dst->last1 = src->last1; | ||
| 75 | dst->last2 = src->last2; | ||
| 76 | dst->last1inv = src->last1inv; | ||
| 77 | dst->last2inv = src->last2inv; | ||
| 78 | dst->sols = src->sols; | ||
| 79 | dst->sols_mutex = src->sols_mutex; | ||
| 80 | dst->current_alg = src->current_alg; | ||
| 81 | |||
| 82 | copy_estimatedata(src->ed, dst->ed); | ||
| 83 | } | ||
| 84 | |||
| 85 | static void | ||
| 86 | dfs(DfsArg *arg) | ||
| 87 | { | ||
| 88 | bool sw = false; | ||
| 89 | |||
| 90 | if (dfs_stop(arg)) | ||
| 91 | return; | ||
| 92 | |||
| 93 | if (dfs_check_solved(arg)) | ||
| 94 | return; | ||
| 95 | 63 | ||
| 96 | if (arg->step->final && (sw = dfs_switch(arg))) | 64 | dst->cube = src->cube; |
| 97 | invert_branch(arg); | 65 | dst->t = src->t; |
| 98 | dfs_branch(arg); | 66 | dst->sa = src->sa; |
| 67 | dst->opts = src->opts; | ||
| 68 | dst->d = src->d; | ||
| 69 | dst->bound = src->bound; /* In theory not needed */ | ||
| 70 | dst->niss = src->niss; | ||
| 71 | dst->sols = src->sols; | ||
| 72 | dst->sols_mutex = src->sols_mutex; | ||
| 73 | dst->current_alg = src->current_alg; | ||
| 99 | 74 | ||
| 100 | if (arg->opts->can_niss && !arg->niss && niss_makes_sense(arg)) | 75 | for (i = 0; i < 2; i++) { |
| 101 | dfs_niss(arg); | 76 | dst->last[i] = src->last[i]; |
| 77 | dst->lastinv[i] = src->lastinv[i]; | ||
| 78 | } | ||
| 102 | 79 | ||
| 103 | if (sw) | 80 | for (i = 0; i < src->sa->n_coord; i++) { |
| 104 | invert_branch(arg); | 81 | dst->ind[i].val = src->ind[i].val; |
| 82 | dst->ind[i].t = src->ind[i].t; | ||
| 83 | } | ||
| 105 | } | 84 | } |
| 106 | 85 | ||
| 107 | static void | 86 | static void |
| 108 | dfs_branch(DfsArg *arg) | 87 | dfs(DfsArg *arg) |
| 109 | { | 88 | { |
| 110 | int i; | 89 | int i; |
| 111 | Move m; | 90 | Move m; |
| 112 | DfsArg *newarg; | 91 | DfsArg newarg; |
| 113 | 92 | ||
| 114 | newarg = malloc(sizeof(DfsArg)); | 93 | if (dfs_move_checkstop(arg)) |
| 115 | newarg->ed = malloc(sizeof(EstimateData)); | 94 | return; |
| 116 | |||
| 117 | for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++) { | ||
| 118 | m = arg->step->moveset->sorted_moves[i]; | ||
| 119 | if (allowed_next(m, arg)) { | ||
| 120 | copy_dfsarg(arg, newarg); | ||
| 121 | newarg->last2 = arg->last1; | ||
| 122 | newarg->last1 = m; | ||
| 123 | newarg->cube = apply_move(m, arg->cube); | ||
| 124 | append_move(arg->current_alg, m, newarg->niss); | ||
| 125 | 95 | ||
| 126 | dfs(newarg); | 96 | if (arg->bound == 0) { |
| 97 | if (arg->current_alg->len == arg->d) | ||
| 98 | dfs_add_sol(arg); | ||
| 99 | return; | ||
| 100 | } | ||
| 127 | 101 | ||
| 102 | for (i = 0; arg->sa->moveset->sorted_moves[i] != NULLMOVE; i++) { | ||
| 103 | m = arg->sa->moveset->sorted_moves[i]; | ||
| 104 | if (allowed_next(m, arg->sa, arg->last[0], arg->last[1])) { | ||
| 105 | copy_dfsarg(arg, &newarg); | ||
| 106 | newarg.last[1] = arg->last[0]; | ||
| 107 | newarg.last[0] = m; | ||
| 108 | append_move(arg->current_alg, m, newarg.niss); | ||
| 109 | dfs(&newarg); | ||
| 128 | arg->current_alg->len--; | 110 | arg->current_alg->len--; |
| 129 | } | 111 | } |
| 130 | } | 112 | } |
| 131 | 113 | ||
| 132 | free(newarg->ed); | 114 | if (niss_makes_sense(arg)) |
| 133 | free(newarg); | 115 | dfs_niss(arg); |
| 134 | } | 116 | } |
| 135 | 117 | ||
| 136 | static bool | 118 | static void |
| 137 | dfs_check_solved(DfsArg *arg) | 119 | dfs_add_sol(DfsArg *arg) |
| 138 | { | 120 | { |
| 139 | if (!arg->step->is_done(arg->cube)) | 121 | bool valid, accepted, nisscanc; |
| 140 | return false; | ||
| 141 | |||
| 142 | if (arg->current_alg->len == arg->d) { | ||
| 143 | if ((arg->step->is_valid(arg->current_alg) || arg->opts->all) | ||
| 144 | && (!arg->step->final || !cancel_niss(arg))) { | ||
| 145 | |||
| 146 | pthread_mutex_lock(arg->sols_mutex); | ||
| 147 | |||
| 148 | if (arg->sols->len < arg->opts->max_solutions) { | ||
| 149 | append_alg(arg->sols, arg->current_alg); | ||
| 150 | 122 | ||
| 151 | transform_alg( | 123 | valid = arg->sa->is_valid==NULL || arg->sa->is_valid(arg->current_alg); |
| 152 | inverse_trans(arg->t), | 124 | accepted = valid || arg->opts->all; |
| 153 | arg->sols->last->alg | 125 | nisscanc = arg->sa->final && cancel_niss(arg); |
| 154 | ); | ||
| 155 | if (arg->step->final) | ||
| 156 | inplace(unniss, arg->sols->last->alg); | ||
| 157 | 126 | ||
| 158 | if (arg->opts->verbose) | 127 | if (accepted && !nisscanc) { |
| 159 | print_alg(arg->sols->last->alg, false); | 128 | pthread_mutex_lock(arg->sols_mutex); |
| 160 | } | ||
| 161 | 129 | ||
| 162 | pthread_mutex_unlock(arg->sols_mutex); | 130 | if (arg->sols->len < arg->opts->max_solutions) { |
| 131 | append_alg(arg->sols, arg->current_alg); | ||
| 132 | transform_alg( | ||
| 133 | inverse_trans(arg->t), arg->sols->last->alg); | ||
| 134 | if (arg->opts->verbose) | ||
| 135 | print_alg(arg->sols->last->alg, false); | ||
| 163 | } | 136 | } |
| 164 | } | ||
| 165 | 137 | ||
| 166 | return true; | 138 | pthread_mutex_unlock(arg->sols_mutex); |
| 139 | } | ||
| 167 | } | 140 | } |
| 168 | 141 | ||
| 169 | static void | 142 | static void |
| 170 | dfs_niss(DfsArg *arg) | 143 | dfs_niss(DfsArg *arg) |
| 171 | { | 144 | { |
| 172 | DfsArg *newarg; | 145 | DfsArg newarg; |
| 146 | Alg *inv; | ||
| 147 | Cube *c; | ||
| 148 | |||
| 149 | copy_dfsarg(arg, &newarg); | ||
| 173 | 150 | ||
| 174 | newarg = malloc(sizeof(DfsArg)); | 151 | /* Invert current alg and scramble */ |
| 175 | newarg->ed = malloc(sizeof(EstimateData)); | 152 | newarg.cube = malloc(sizeof(Cube)); |
| 153 | inv = inverse_alg(arg->current_alg); | ||
| 154 | c = malloc(sizeof(Cube)); | ||
| 155 | make_solved(newarg.cube); | ||
| 156 | apply_alg(inv, newarg.cube); | ||
| 157 | copy_cube(arg->cube, c); | ||
| 158 | invert_cube(c); | ||
| 159 | compose(c, newarg.cube); | ||
| 176 | 160 | ||
| 177 | copy_dfsarg(arg, newarg); | 161 | /* New indexes */ |
| 178 | swapmove(&(newarg->last1), &(newarg->last1inv)); | 162 | compute_ind(newarg.sa, newarg.cube, newarg.ind); |
| 179 | swapmove(&(newarg->last2), &(newarg->last2inv)); | ||
| 180 | newarg->niss = !(arg->niss); | ||
| 181 | newarg->cube = inverse_cube(arg->cube); | ||
| 182 | 163 | ||
| 183 | dfs(newarg); | 164 | swapmove(&(newarg.last[0]), &(newarg.lastinv[0])); |
| 165 | swapmove(&(newarg.last[1]), &(newarg.lastinv[1])); | ||
| 166 | newarg.niss = !(arg->niss); | ||
| 184 | 167 | ||
| 185 | free(newarg->ed); | 168 | dfs(&newarg); |
| 186 | free(newarg); | 169 | |
| 170 | free_alg(inv); | ||
| 171 | free(c); | ||
| 172 | free(newarg.cube); | ||
| 187 | } | 173 | } |
| 188 | 174 | ||
| 189 | static bool | 175 | static bool |
| 190 | dfs_stop(DfsArg *arg) | 176 | dfs_move_checkstop(DfsArg *arg) |
| 191 | { | 177 | { |
| 192 | int lowerbound; | ||
| 193 | bool b; | 178 | bool b; |
| 179 | int i, goal; | ||
| 180 | Move mm; | ||
| 181 | Trans tt = uf; /* Avoid uninitialized warning */ | ||
| 182 | |||
| 183 | /* Moving */ | ||
| 184 | if (arg->last[0] != NULLMOVE) { | ||
| 185 | for (i = 0; i < arg->sa->n_coord; i++) { | ||
| 186 | mm = transform_move(arg->ind[i].t, arg->last[0]); | ||
| 187 | arg->ind[i].val = move_coord(arg->sa->coord[i], | ||
| 188 | mm, arg->ind[i].val, &tt); | ||
| 189 | arg->ind[i].t = transform_trans(tt, arg->ind[i].t); | ||
| 190 | } | ||
| 191 | } | ||
| 194 | 192 | ||
| 195 | lowerbound = arg->step->estimate(arg); | 193 | /* Computing bound for coordinates */ |
| 194 | goal = arg->d - arg->current_alg->len; | ||
| 195 | arg->bound = estimate_stepalt(arg->sa, arg->ind, goal); | ||
| 196 | if (arg->opts->can_niss && !arg->niss) | 196 | if (arg->opts->can_niss && !arg->niss) |
| 197 | lowerbound = MIN(1, lowerbound); | 197 | arg->bound = MIN(1, arg->bound); |
| 198 | 198 | ||
| 199 | if (arg->current_alg->len + lowerbound > arg->d) { | 199 | if (arg->bound > goal) { |
| 200 | b = true; | 200 | b = true; |
| 201 | } else { | 201 | } else { |
| 202 | pthread_mutex_lock(arg->sols_mutex); | 202 | pthread_mutex_lock(arg->sols_mutex); |
| 203 | b = arg->sols->len >= arg->opts->max_solutions; | 203 | b = arg->sols->len >= arg->opts->max_solutions; |
| @@ -207,37 +207,12 @@ dfs_stop(DfsArg *arg) | |||
| 207 | return b; | 207 | return b; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | static bool | ||
| 211 | dfs_switch(DfsArg *arg) | ||
| 212 | { | ||
| 213 | int i, bn, bi; | ||
| 214 | |||
| 215 | bn = 0; | ||
| 216 | for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++) | ||
| 217 | if (allowed_next(arg->step->moveset->sorted_moves[i], arg)) | ||
| 218 | bn++; | ||
| 219 | |||
| 220 | swapmove(&(arg->last1), &(arg->last1inv)); | ||
| 221 | swapmove(&(arg->last2), &(arg->last2inv)); | ||
| 222 | swapu64(&(arg->badmoves), &(arg->badmovesinv)); | ||
| 223 | |||
| 224 | bi = 0; | ||
| 225 | for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++) | ||
| 226 | if (allowed_next(arg->step->moveset->sorted_moves[i], arg)) | ||
| 227 | bi++; | ||
| 228 | |||
| 229 | swapmove(&(arg->last1), &(arg->last1inv)); | ||
| 230 | swapmove(&(arg->last2), &(arg->last2inv)); | ||
| 231 | swapu64(&(arg->badmoves), &(arg->badmovesinv)); | ||
| 232 | |||
| 233 | return bi < bn; | ||
| 234 | } | ||
| 235 | |||
| 236 | static void * | 210 | static void * |
| 237 | instance_thread(void *arg) | 211 | instance_thread(void *arg) |
| 238 | { | 212 | { |
| 239 | bool b; | 213 | bool b, inv; |
| 240 | Cube c; | 214 | Cube c; |
| 215 | Move m; | ||
| 241 | ThreadDataSolve *td; | 216 | ThreadDataSolve *td; |
| 242 | AlgListNode *node; | 217 | AlgListNode *node; |
| 243 | DfsArg darg; | 218 | DfsArg darg; |
| @@ -257,68 +232,46 @@ instance_thread(void *arg) | |||
| 257 | if (b) | 232 | if (b) |
| 258 | break; | 233 | break; |
| 259 | 234 | ||
| 260 | c = node->alg->inv[0] ? | 235 | inv = node->alg->inv[0]; |
| 261 | apply_move(node->alg->move[0], inverse_cube(td->cube)) : | 236 | m = node->alg->move[0]; |
| 262 | apply_move(node->alg->move[0], td->cube); | 237 | |
| 238 | copy_cube(td->arg.cube, &c); | ||
| 239 | if (inv) | ||
| 240 | invert_cube(&c); | ||
| 263 | 241 | ||
| 264 | darg.step = td->step; | 242 | copy_dfsarg(&td->arg, &darg); |
| 265 | darg.opts = td->opts; | 243 | compute_ind(td->arg.sa, &c, darg.ind); |
| 266 | darg.t = td->t; | 244 | darg.cube = &c; |
| 267 | darg.cube = c; | 245 | |
| 268 | darg.d = td->depth; | 246 | darg.niss = inv; |
| 269 | darg.niss = node->alg->inv[0]; | 247 | darg.last[0] = m; |
| 270 | darg.last1 = node->alg->move[0]; | 248 | darg.last[1] = NULLMOVE; |
| 271 | darg.last2 = NULLMOVE; | 249 | darg.lastinv[0] = NULLMOVE; |
| 272 | darg.last1inv = NULLMOVE; | 250 | darg.lastinv[1] = NULLMOVE; |
| 273 | darg.last2inv = NULLMOVE; | ||
| 274 | darg.sols = td->sols; | ||
| 275 | darg.sols_mutex = td->sols_mutex; | ||
| 276 | darg.current_alg = new_alg(""); | 251 | darg.current_alg = new_alg(""); |
| 277 | append_move(darg.current_alg, node->alg->move[0], | 252 | append_move(darg.current_alg, m, inv); |
| 278 | node->alg->inv[0]); | ||
| 279 | darg.ed = malloc(sizeof(EstimateData)); | ||
| 280 | reset_estimatedata(darg.ed); | ||
| 281 | darg.badmoves = 0; | ||
| 282 | darg.badmovesinv = 0; | ||
| 283 | 253 | ||
| 284 | dfs(&darg); | 254 | dfs(&darg); |
| 285 | 255 | ||
| 286 | free_alg(darg.current_alg); | 256 | free_alg(darg.current_alg); |
| 287 | free(darg.ed); | ||
| 288 | } | 257 | } |
| 289 | 258 | ||
| 290 | return NULL; | 259 | return NULL; |
| 291 | } | 260 | } |
| 292 | 261 | ||
| 293 | static void | 262 | static void |
| 294 | invert_branch(DfsArg *arg) | 263 | multidfs(DfsArg *arg) |
| 295 | { | ||
| 296 | Cube aux; | ||
| 297 | |||
| 298 | aux = arg->cube; | ||
| 299 | arg->cube = is_solved(arg->inverse) ? | ||
| 300 | inverse_cube(arg->cube) : arg->inverse; | ||
| 301 | arg->inverse = aux; | ||
| 302 | |||
| 303 | swapu64(&(arg->badmoves), &(arg->badmovesinv)); | ||
| 304 | arg->niss = !(arg->niss); | ||
| 305 | swapmove(&(arg->last1), &(arg->last1inv)); | ||
| 306 | swapmove(&(arg->last2), &(arg->last2inv)); | ||
| 307 | invert_estimatedata(arg->ed); | ||
| 308 | } | ||
| 309 | |||
| 310 | static void | ||
| 311 | multidfs(Cube c, Trans tr, Step *s, SolveOptions *opts, AlgList *sols, int d) | ||
| 312 | { | 264 | { |
| 313 | int i; | 265 | int i; |
| 266 | Cube local_cube; | ||
| 314 | Alg *alg; | 267 | Alg *alg; |
| 315 | AlgList *start; | 268 | AlgList *start; |
| 316 | AlgListNode **node; | 269 | AlgListNode **node; |
| 317 | pthread_t t[opts->nthreads]; | 270 | pthread_t t[arg->opts->nthreads]; |
| 318 | ThreadDataSolve td[opts->nthreads]; | 271 | ThreadDataSolve td[arg->opts->nthreads]; |
| 319 | pthread_mutex_t *start_mutex, *sols_mutex; | 272 | pthread_mutex_t *start_mutex, *sols_mutex; |
| 320 | 273 | ||
| 321 | node = malloc(sizeof(AlgListNode *)); | 274 | node = malloc(sizeof(AlgListNode *)); |
| 322 | start_mutex = malloc(sizeof(pthread_mutex_t)); | 275 | start_mutex = malloc(sizeof(pthread_mutex_t)); |
| 323 | sols_mutex = malloc(sizeof(pthread_mutex_t)); | 276 | sols_mutex = malloc(sizeof(pthread_mutex_t)); |
| 324 | 277 | ||
| @@ -326,11 +279,11 @@ multidfs(Cube c, Trans tr, Step *s, SolveOptions *opts, AlgList *sols, int d) | |||
| 326 | pthread_mutex_init(start_mutex, NULL); | 279 | pthread_mutex_init(start_mutex, NULL); |
| 327 | pthread_mutex_init(sols_mutex, NULL); | 280 | pthread_mutex_init(sols_mutex, NULL); |
| 328 | 281 | ||
| 329 | for (i = 0; s->moveset->sorted_moves[i] != NULLMOVE; i++) { | 282 | for (i = 0; arg->sa->moveset->sorted_moves[i] != NULLMOVE; i++) { |
| 330 | alg = new_alg(""); | 283 | alg = new_alg(""); |
| 331 | append_move(alg, s->moveset->sorted_moves[i], false); | 284 | append_move(alg, arg->sa->moveset->sorted_moves[i], false); |
| 332 | append_alg(start, alg); | 285 | append_alg(start, alg); |
| 333 | if (opts->can_niss) { | 286 | if (arg->opts->can_niss && !arg->sa->final) { |
| 334 | alg->inv[0] = true; | 287 | alg->inv[0] = true; |
| 335 | append_alg(start, alg); | 288 | append_alg(start, alg); |
| 336 | } | 289 | } |
| @@ -338,22 +291,22 @@ multidfs(Cube c, Trans tr, Step *s, SolveOptions *opts, AlgList *sols, int d) | |||
| 338 | } | 291 | } |
| 339 | *node = start->first; | 292 | *node = start->first; |
| 340 | 293 | ||
| 341 | for (i = 0; i < opts->nthreads; i++) { | 294 | copy_cube(arg->cube, &local_cube); |
| 342 | td[i].thid = i; | 295 | |
| 343 | td[i].t = tr; | 296 | for (i = 0; i < arg->opts->nthreads; i++) { |
| 344 | td[i].cube = c; | 297 | copy_dfsarg(arg, &(td[i].arg)); |
| 345 | td[i].step = s; | 298 | td[i].arg.cube = &local_cube; |
| 346 | td[i].depth = d; | 299 | td[i].arg.sols_mutex = sols_mutex; |
| 347 | td[i].opts = opts; | 300 | |
| 348 | td[i].start = start; | 301 | td[i].thid = i; |
| 349 | td[i].node = node; | 302 | td[i].start = start; |
| 350 | td[i].sols = sols; | 303 | td[i].node = node; |
| 351 | td[i].start_mutex = start_mutex; | 304 | td[i].start_mutex = start_mutex; |
| 352 | td[i].sols_mutex = sols_mutex; | 305 | |
| 353 | pthread_create(&t[i], NULL, instance_thread, &td[i]); | 306 | pthread_create(&t[i], NULL, instance_thread, &td[i]); |
| 354 | } | 307 | } |
| 355 | 308 | ||
| 356 | for (i = 0; i < opts->nthreads; i++) | 309 | for (i = 0; i < arg->opts->nthreads; i++) |
| 357 | pthread_join(t[i], NULL); | 310 | pthread_join(t[i], NULL); |
| 358 | 311 | ||
| 359 | free_alglist(start); | 312 | free_alglist(start); |
| @@ -367,8 +320,13 @@ niss_makes_sense(DfsArg *arg) | |||
| 367 | { | 320 | { |
| 368 | Cube testcube; | 321 | Cube testcube; |
| 369 | 322 | ||
| 370 | testcube = apply_move(inverse_move(arg->last1), (Cube){0}); | 323 | if (arg->sa->final || arg->niss || !arg->opts->can_niss) |
| 371 | return arg->current_alg->len == 0 || !arg->step->is_done(testcube); | 324 | return false; |
| 325 | |||
| 326 | make_solved(&testcube); | ||
| 327 | apply_move(inverse_move(arg->last[0]), &testcube); | ||
| 328 | return arg->current_alg->len == 0 || | ||
| 329 | estimate_stepalt(arg->sa, arg->ind, 0) > 0; | ||
| 372 | } | 330 | } |
| 373 | 331 | ||
| 374 | static bool | 332 | static bool |
| @@ -386,62 +344,84 @@ solvestop(int d, int op, SolveOptions *opts, AlgList *sols) | |||
| 386 | /* Public functions **********************************************************/ | 344 | /* Public functions **********************************************************/ |
| 387 | 345 | ||
| 388 | AlgList * | 346 | AlgList * |
| 389 | solve(Cube cube, Step *step, SolveOptions *opts) | 347 | solve(Cube *cube, Step *step, SolveOptions *opts) |
| 390 | { | 348 | { |
| 391 | bool ready; | 349 | int i, d, op; |
| 392 | int i, d, op, nt; | 350 | bool ready[99], one_ready, zerosol; |
| 393 | AlgList *sols; | 351 | Movable ind[99][10]; |
| 394 | Cube c; | 352 | AlgList *s; |
| 395 | Trans tt[NTRANS]; | 353 | Cube *c[99]; |
| 354 | DfsArg arg[99]; | ||
| 396 | 355 | ||
| 397 | prepare_step(step, opts); | 356 | prepare_step(step, opts); |
| 357 | s = new_alglist(); | ||
| 398 | 358 | ||
| 399 | if (step->detect != NULL) { | 359 | for (i = 0, one_ready = false; step->alt[i] != NULL; i++) { |
| 400 | nt = step->detect(cube, tt); | 360 | c[i] = malloc(sizeof(Cube)); |
| 401 | } else { | 361 | copy_cube(cube, c[i]); |
| 402 | tt[0] = step->pre_trans; | 362 | apply_trans(step->t[i], c[i]); |
| 403 | ready = step->ready == NULL || | ||
| 404 | step->ready(apply_trans(tt[0], cube)); | ||
| 405 | nt = ready ? 1 : 0; | ||
| 406 | } | ||
| 407 | 363 | ||
| 408 | sols = new_alglist(); | 364 | arg[i].cube = c[i]; |
| 365 | arg[i].t = step->t[i]; | ||
| 366 | arg[i].sa = step->alt[i]; | ||
| 367 | arg[i].opts = opts; | ||
| 368 | arg[i].sols = s; | ||
| 409 | 369 | ||
| 410 | if (nt == 0) { | 370 | if ((ready[i] = step->alt[i]->ready(c[i]))) { |
| 371 | one_ready = true; | ||
| 372 | /* Only for local use for 0 moves solutions */ | ||
| 373 | compute_ind(step->alt[i], c[i], ind[i]); | ||
| 374 | } | ||
| 375 | } | ||
| 376 | if (!one_ready) { | ||
| 411 | fprintf(stderr, "Cube not ready for solving step: "); | 377 | fprintf(stderr, "Cube not ready for solving step: "); |
| 412 | fprintf(stderr, "%s\n", step->ready_msg); | 378 | fprintf(stderr, "%s\n", step->ready_msg); |
| 413 | return sols; | 379 | return s; |
| 414 | } | 380 | } |
| 415 | 381 | ||
| 416 | if (opts->min_moves == 0) { | 382 | /* If the empty moves sequence is a solution for one of the |
| 417 | for (i = 0; i < nt; i++) { | 383 | * alternatives, all longer solutions will be discarded, so we may |
| 418 | c = apply_trans(tt[i], cube); | 384 | * just set its ready[] value to false. If the solution is accepted |
| 419 | if (step->is_done(c)) { | 385 | * we append it and start searching from d = 1. */ |
| 420 | append_alg(sols, new_alg("")); | 386 | for (i = 0, zerosol = false; step->alt[i] != NULL; i++) { |
| 421 | return sols; | 387 | if (ready[i] && estimate_stepalt(step->alt[i],ind[i],0) == 0) { |
| 422 | } | 388 | ready[i] = false; |
| 389 | zerosol = true; | ||
| 423 | } | 390 | } |
| 424 | } | 391 | } |
| 392 | if (zerosol && opts->min_moves == 0) { | ||
| 393 | append_alg(s, new_alg("")); | ||
| 394 | opts->min_moves = 1; | ||
| 395 | if (opts->verbose) | ||
| 396 | printf("Step is already solved" | ||
| 397 | "(empty alg is a solution)\n"); | ||
| 398 | } | ||
| 425 | 399 | ||
| 426 | op = -1; | 400 | for (d = opts->min_moves, op = -1; !solvestop(d, op, opts, s); d++) { |
| 427 | for (d = opts->min_moves; !solvestop(d, op, opts, sols); d++) { | ||
| 428 | if (opts->verbose) | 401 | if (opts->verbose) |
| 429 | fprintf(stderr, "Searching depth %d\n", d); | 402 | fprintf(stderr, "Searching depth %d\n", d); |
| 430 | 403 | ||
| 431 | for (i = 0; i < nt && !solvestop(d, op, opts, sols); i++) { | 404 | for (i=0; step->alt[i]!=NULL && !solvestop(d,op,opts,s); i++) { |
| 432 | c = apply_trans(tt[i], cube); | 405 | if (!ready[i]) |
| 433 | multidfs(c, tt[i], step, opts, sols, d); | 406 | continue; |
| 434 | if (sols->len > 0 && op == -1) | 407 | |
| 408 | arg[i].d = d; | ||
| 409 | multidfs(&arg[i]); | ||
| 410 | |||
| 411 | if (s->len > 0 && op == -1) | ||
| 435 | op = d; | 412 | op = d; |
| 436 | } | 413 | } |
| 437 | } | 414 | } |
| 438 | 415 | ||
| 439 | return sols; | 416 | for (i = 0; step->alt[i] != NULL; i++) |
| 417 | free(c[i]); | ||
| 418 | |||
| 419 | return s; | ||
| 440 | } | 420 | } |
| 441 | 421 | ||
| 442 | /* TODO: make more general! */ | 422 | /* TODO: make more general! */ |
| 443 | Alg * | 423 | Alg * |
| 444 | solve_2phase(Cube cube, int nthreads) | 424 | solve_2phase(Cube *cube, int nthreads) |
| 445 | { | 425 | { |
| 446 | int bestlen, newb; | 426 | int bestlen, newb; |
| 447 | Alg *bestalg, *ret; | 427 | Alg *bestalg, *ret; |
| @@ -466,18 +446,19 @@ solve_2phase(Cube cube, int nthreads) | |||
| 466 | opts2.can_niss = false; | 446 | opts2.can_niss = false; |
| 467 | opts2.verbose = false; | 447 | opts2.verbose = false; |
| 468 | 448 | ||
| 469 | /* We skip step1 if it is solved on any axis */ | 449 | /* We skip step1 if it is solved on U/D */ |
| 470 | if (drany_HTM.is_done(cube)) { | 450 | if (check_drud(cube)) { |
| 471 | sols1 = new_alglist(); | 451 | sols1 = new_alglist(); |
| 472 | append_alg(sols1, new_alg("")); | 452 | append_alg(sols1, new_alg("")); |
| 473 | } else { | 453 | } else { |
| 474 | sols1 = solve(cube, &drany_HTM, &opts1); | 454 | sols1 = solve(cube, &drud_HTM, &opts1); |
| 475 | } | 455 | } |
| 476 | bestalg = new_alg(""); | 456 | bestalg = new_alg(""); |
| 477 | bestlen = 999; | 457 | bestlen = 999; |
| 478 | for (i = sols1->first; i != NULL; i = i->next) { | 458 | for (i = sols1->first; i != NULL; i = i->next) { |
| 479 | c = apply_alg(i->alg, cube); | 459 | copy_cube(cube, &c); |
| 480 | sols2 = solve(c, &dranyfin_DR, &opts2); | 460 | apply_alg(i->alg, &c); |
| 461 | sols2 = solve(&c, &dranyfin_DR, &opts2); | ||
| 481 | 462 | ||
| 482 | if (sols2->len > 0) { | 463 | if (sols2->len > 0) { |
| 483 | newb = i->alg->len + sols2->first->alg->len; | 464 | newb = i->alg->len + sols2->first->alg->len; |
diff --git a/src/solve.h b/src/solve.h index 6ce6609..9039e4a 100644 --- a/src/solve.h +++ b/src/solve.h | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | #include "steps.h" | 5 | #include "steps.h" |
| 6 | #include "trans.h" | 6 | #include "trans.h" |
| 7 | 7 | ||
| 8 | AlgList * solve(Cube cube, Step *step, SolveOptions *opts); | 8 | AlgList * solve(Cube *cube, Step *step, SolveOptions *opts); |
| 9 | Alg * solve_2phase(Cube cube, int nthreads); | 9 | Alg * solve_2phase(Cube *cube, int nthreads); |
| 10 | 10 | ||
| 11 | #endif | 11 | #endif |
diff --git a/src/steps.c b/src/steps.c index 3189811..81af269 100644 --- a/src/steps.c +++ b/src/steps.c | |||
| @@ -1,1372 +1,112 @@ | |||
| 1 | #include "steps.h" | 1 | #define STEPS_C |
| 2 | |||
| 3 | #define UPDATECHECKSTOP(a, b, c) if ((a=(MAX((a),(b))))>(c)) return (a); | ||
| 4 | |||
| 5 | /* Checkers, estimators and validators ***************************************/ | ||
| 6 | |||
| 7 | static bool check_centers(Cube cube); | ||
| 8 | static bool check_coud_HTM(Cube cube); | ||
| 9 | static bool check_coud_URF(Cube cube); | ||
| 10 | static bool check_corners_HTM(Cube cube); | ||
| 11 | static bool check_corners_URF(Cube cube); | ||
| 12 | static bool check_cornershtr(Cube cube); | ||
| 13 | static bool check_eofb(Cube cube); | ||
| 14 | static bool check_drud(Cube cube); | ||
| 15 | static bool check_htr(Cube cube); | ||
| 16 | |||
| 17 | static int estimate_eofb_HTM(DfsArg *arg); | ||
| 18 | static int estimate_coud_HTM(DfsArg *arg); | ||
| 19 | static int estimate_coud_URF(DfsArg *arg); | ||
| 20 | static int estimate_corners_HTM(DfsArg *arg); | ||
| 21 | static int estimate_cornershtr_HTM(DfsArg *arg); | ||
| 22 | static int estimate_corners_URF(DfsArg *arg); | ||
| 23 | static int estimate_cornershtr_URF(DfsArg *arg); | ||
| 24 | static int estimate_drud_HTM(DfsArg *arg); | ||
| 25 | static int estimate_drud_eofb(DfsArg *arg); | ||
| 26 | static int estimate_dr_eofb(DfsArg *arg); | ||
| 27 | static int estimate_drudfin_drud(DfsArg *arg); | ||
| 28 | static int estimate_htr_drud(DfsArg *arg); | ||
| 29 | static int estimate_htrfin_htr(DfsArg *arg); | ||
| 30 | static int estimate_nxopt31_HTM(DfsArg *arg); | ||
| 31 | static int estimate_light_HTM(DfsArg *arg); | ||
| 32 | |||
| 33 | static int estimate_nxoptlike(DfsArg *arg, PruneData *pd); | ||
| 34 | |||
| 35 | static bool always_valid(Alg *alg); | ||
| 36 | static bool validate_singlecw_ending(Alg *alg); | ||
| 37 | |||
| 38 | /* Pre-transformation detectors **********************************************/ | ||
| 39 | |||
| 40 | static int detect_pretrans_eofb(Cube cube, Trans *ret); | ||
| 41 | static int detect_pretrans_drud(Cube cube, Trans *ret); | ||
| 42 | static int detect_pretrans_void_3axis(Cube cube, Trans *ret); | ||
| 43 | |||
| 44 | /* Messages for when cube is not ready ***************************************/ | ||
| 45 | |||
| 46 | static char check_centers_msg[100] = "cube must be oriented (centers solved)"; | ||
| 47 | static char check_eo_msg[100] = "EO must be solved on given axis"; | ||
| 48 | static char check_dr_msg[100] = "DR must be solved on given axis"; | ||
| 49 | static char check_htr_msg[100] = "HTR must be solved"; | ||
| 50 | static char check_drany_msg[100] = "DR must be solved on at least one axis"; | ||
| 51 | |||
| 52 | /* Steps *********************************************************************/ | ||
| 53 | |||
| 54 | /* Optimal solvers *******************/ | ||
| 55 | |||
| 56 | Step | ||
| 57 | optimal_HTM = { | ||
| 58 | .shortname = "optimal", | ||
| 59 | .name = "Optimal solve (in HTM)", | ||
| 60 | |||
| 61 | .final = true, | ||
| 62 | .is_done = is_solved, | ||
| 63 | .estimate = estimate_nxopt31_HTM, | ||
| 64 | .ready = check_centers, | ||
| 65 | .ready_msg = check_centers_msg, | ||
| 66 | .is_valid = always_valid, | ||
| 67 | .moveset = &moveset_HTM, | ||
| 68 | |||
| 69 | .pre_trans = uf, | ||
| 70 | |||
| 71 | .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, | ||
| 72 | .ntables = 2, | ||
| 73 | }; | ||
| 74 | |||
| 75 | Step | ||
| 76 | optimal_light_HTM = { | ||
| 77 | .shortname = "light", | ||
| 78 | .name = "Optimal solve (in HTM), small table (500Mb RAM total)", | ||
| 79 | |||
| 80 | .final = true, | ||
| 81 | .is_done = is_solved, | ||
| 82 | .estimate = estimate_light_HTM, | ||
| 83 | .ready = check_centers, | ||
| 84 | .ready_msg = check_centers_msg, | ||
| 85 | .is_valid = always_valid, | ||
| 86 | .moveset = &moveset_HTM, | ||
| 87 | |||
| 88 | .pre_trans = uf, | ||
| 89 | |||
| 90 | .tables = {&pd_drud_sym16_HTM, &pd_corners_HTM}, | ||
| 91 | .ntables = 2, | ||
| 92 | }; | ||
| 93 | |||
| 94 | /* Optimal after EO ******************/ | ||
| 95 | |||
| 96 | Step | ||
| 97 | eofin_eo = { | ||
| 98 | .shortname = "eofin", | ||
| 99 | .name = "Optimal solve after EO without breaking EO (detected)", | ||
| 100 | |||
| 101 | .final = true, | ||
| 102 | .is_done = is_solved, | ||
| 103 | .estimate = estimate_nxopt31_HTM, | ||
| 104 | .ready = check_eofb, | ||
| 105 | .ready_msg = check_eo_msg, | ||
| 106 | .is_valid = always_valid, | ||
| 107 | .moveset = &moveset_eofb, | ||
| 108 | |||
| 109 | .detect = detect_pretrans_eofb, | ||
| 110 | |||
| 111 | .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, | ||
| 112 | .ntables = 2, | ||
| 113 | }; | ||
| 114 | |||
| 115 | Step | ||
| 116 | eofbfin_eofb = { | ||
| 117 | .shortname = "eofbfin", | ||
| 118 | .name = "Optimal after EO on F/B without breaking EO", | ||
| 119 | |||
| 120 | .final = true, | ||
| 121 | .is_done = is_solved, | ||
| 122 | .estimate = estimate_nxopt31_HTM, | ||
| 123 | .ready = check_eofb, | ||
| 124 | .ready_msg = check_eo_msg, | ||
| 125 | .is_valid = always_valid, | ||
| 126 | .moveset = &moveset_eofb, | ||
| 127 | |||
| 128 | .pre_trans = uf, | ||
| 129 | |||
| 130 | .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, | ||
| 131 | .ntables = 2, | ||
| 132 | }; | ||
| 133 | |||
| 134 | Step | ||
| 135 | eorlfin_eorl = { | ||
| 136 | .shortname = "eorlfin", | ||
| 137 | .name = "Optimal after EO on R/L without breaking EO", | ||
| 138 | |||
| 139 | .final = true, | ||
| 140 | .is_done = is_solved, | ||
| 141 | .estimate = estimate_nxopt31_HTM, | ||
| 142 | .ready = check_eofb, | ||
| 143 | .ready_msg = check_eo_msg, | ||
| 144 | .is_valid = always_valid, | ||
| 145 | .moveset = &moveset_eofb, | ||
| 146 | |||
| 147 | .pre_trans = ur, | ||
| 148 | |||
| 149 | .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, | ||
| 150 | .ntables = 2, | ||
| 151 | }; | ||
| 152 | |||
| 153 | Step | ||
| 154 | eoudfin_eoud = { | ||
| 155 | .shortname = "eoudfin", | ||
| 156 | .name = "Optimal after EO on U/D without breaking EO", | ||
| 157 | |||
| 158 | .final = true, | ||
| 159 | .is_done = is_solved, | ||
| 160 | .estimate = estimate_nxopt31_HTM, | ||
| 161 | .ready = check_eofb, | ||
| 162 | .ready_msg = check_eo_msg, | ||
| 163 | .is_valid = always_valid, | ||
| 164 | .moveset = &moveset_eofb, | ||
| 165 | |||
| 166 | .pre_trans = fd, | ||
| 167 | |||
| 168 | .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, | ||
| 169 | .ntables = 2, | ||
| 170 | }; | ||
| 171 | |||
| 172 | /* EO steps **************************/ | ||
| 173 | Step | ||
| 174 | eoany_HTM = { | ||
| 175 | .shortname = "eo", | ||
| 176 | .name = "EO on any axis", | ||
| 177 | |||
| 178 | .final = false, | ||
| 179 | .is_done = check_eofb, | ||
| 180 | .estimate = estimate_eofb_HTM, | ||
| 181 | .ready = check_centers, | ||
| 182 | .ready_msg = check_centers_msg, | ||
| 183 | .is_valid = validate_singlecw_ending, | ||
| 184 | .moveset = &moveset_HTM, | ||
| 185 | |||
| 186 | .detect = detect_pretrans_void_3axis, | ||
| 187 | |||
| 188 | .tables = {&pd_eofb_HTM}, | ||
| 189 | .ntables = 1, | ||
| 190 | }; | ||
| 191 | |||
| 192 | Step | ||
| 193 | eofb_HTM = { | ||
| 194 | .shortname = "eofb", | ||
| 195 | .name = "EO on F/B", | ||
| 196 | |||
| 197 | .final = false, | ||
| 198 | .is_done = check_eofb, | ||
| 199 | .estimate = estimate_eofb_HTM, | ||
| 200 | .ready = check_centers, | ||
| 201 | .ready_msg = check_centers_msg, | ||
| 202 | .is_valid = validate_singlecw_ending, | ||
| 203 | .moveset = &moveset_HTM, | ||
| 204 | |||
| 205 | .pre_trans = uf, | ||
| 206 | |||
| 207 | .tables = {&pd_eofb_HTM}, | ||
| 208 | .ntables = 1, | ||
| 209 | }; | ||
| 210 | |||
| 211 | Step | ||
| 212 | eorl_HTM = { | ||
| 213 | .shortname = "eorl", | ||
| 214 | .name = "EO on R/L", | ||
| 215 | |||
| 216 | .final = false, | ||
| 217 | .is_done = check_eofb, | ||
| 218 | .estimate = estimate_eofb_HTM, | ||
| 219 | .ready = check_centers, | ||
| 220 | .ready_msg = check_centers_msg, | ||
| 221 | .is_valid = validate_singlecw_ending, | ||
| 222 | .moveset = &moveset_HTM, | ||
| 223 | |||
| 224 | .pre_trans = ur, | ||
| 225 | |||
| 226 | .tables = {&pd_eofb_HTM}, | ||
| 227 | .ntables = 1, | ||
| 228 | }; | ||
| 229 | |||
| 230 | Step | ||
| 231 | eoud_HTM = { | ||
| 232 | .shortname = "eoud", | ||
| 233 | .name = "EO on U/D", | ||
| 234 | |||
| 235 | .final = false, | ||
| 236 | .is_done = check_eofb, | ||
| 237 | .estimate = estimate_eofb_HTM, | ||
| 238 | .ready = check_centers, | ||
| 239 | .ready_msg = check_centers_msg, | ||
| 240 | .is_valid = validate_singlecw_ending, | ||
| 241 | .moveset = &moveset_HTM, | ||
| 242 | |||
| 243 | .pre_trans = fd, | ||
| 244 | |||
| 245 | .tables = {&pd_eofb_HTM}, | ||
| 246 | .ntables = 1, | ||
| 247 | }; | ||
| 248 | |||
| 249 | /* CO steps **************************/ | ||
| 250 | Step | ||
| 251 | coany_HTM = { | ||
| 252 | .shortname = "co", | ||
| 253 | .name = "CO on any axis", | ||
| 254 | |||
| 255 | .final = false, | ||
| 256 | .is_done = check_coud_HTM, | ||
| 257 | .estimate = estimate_coud_HTM, | ||
| 258 | .ready = NULL, | ||
| 259 | .is_valid = validate_singlecw_ending, | ||
| 260 | .moveset = &moveset_HTM, | ||
| 261 | |||
| 262 | .detect = detect_pretrans_void_3axis, | ||
| 263 | |||
| 264 | .tables = {&pd_coud_HTM}, | ||
| 265 | .ntables = 1, | ||
| 266 | }; | ||
| 267 | |||
| 268 | Step | ||
| 269 | coud_HTM = { | ||
| 270 | .shortname = "coud", | ||
| 271 | .name = "CO on U/D", | ||
| 272 | |||
| 273 | .final = false, | ||
| 274 | .is_done = check_coud_HTM, | ||
| 275 | .estimate = estimate_coud_HTM, | ||
| 276 | .ready = NULL, | ||
| 277 | .is_valid = validate_singlecw_ending, | ||
| 278 | .moveset = &moveset_HTM, | ||
| 279 | |||
| 280 | .pre_trans = uf, | ||
| 281 | |||
| 282 | .tables = {&pd_coud_HTM}, | ||
| 283 | .ntables = 1, | ||
| 284 | }; | ||
| 285 | |||
| 286 | Step | ||
| 287 | corl_HTM = { | ||
| 288 | .shortname = "corl", | ||
| 289 | .name = "CO on R/L", | ||
| 290 | |||
| 291 | .final = false, | ||
| 292 | .is_done = check_coud_HTM, | ||
| 293 | .estimate = estimate_coud_HTM, | ||
| 294 | .ready = NULL, | ||
| 295 | .is_valid = validate_singlecw_ending, | ||
| 296 | .moveset = &moveset_HTM, | ||
| 297 | |||
| 298 | .pre_trans = rf, | ||
| 299 | |||
| 300 | .tables = {&pd_coud_HTM}, | ||
| 301 | .ntables = 1, | ||
| 302 | }; | ||
| 303 | |||
| 304 | Step | ||
| 305 | cofb_HTM = { | ||
| 306 | .shortname = "cofb", | ||
| 307 | .name = "CO on F/B", | ||
| 308 | |||
| 309 | .final = false, | ||
| 310 | .is_done = check_coud_HTM, | ||
| 311 | .estimate = estimate_coud_HTM, | ||
| 312 | .ready = NULL, | ||
| 313 | .is_valid = validate_singlecw_ending, | ||
| 314 | .moveset = &moveset_HTM, | ||
| 315 | |||
| 316 | .pre_trans = fd, | ||
| 317 | |||
| 318 | .tables = {&pd_coud_HTM}, | ||
| 319 | .ntables = 1, | ||
| 320 | }; | ||
| 321 | |||
| 322 | Step | ||
| 323 | coany_URF = { | ||
| 324 | .shortname = "co-URF", | ||
| 325 | .name = "CO any axis (URF moveset)", | ||
| 326 | |||
| 327 | .final = false, | ||
| 328 | .is_done = check_coud_URF, | ||
| 329 | .estimate = estimate_coud_URF, | ||
| 330 | .ready = NULL, | ||
| 331 | .is_valid = validate_singlecw_ending, | ||
| 332 | .moveset = &moveset_URF, | ||
| 333 | |||
| 334 | .detect = detect_pretrans_void_3axis, | ||
| 335 | |||
| 336 | .tables = {&pd_coud_HTM}, | ||
| 337 | .ntables = 1, | ||
| 338 | }; | ||
| 339 | |||
| 340 | Step | ||
| 341 | coud_URF = { | ||
| 342 | .shortname = "coud-URF", | ||
| 343 | .name = "CO on U/D (URF moveset)", | ||
| 344 | |||
| 345 | .final = false, | ||
| 346 | .is_done = check_coud_URF, | ||
| 347 | .estimate = estimate_coud_URF, | ||
| 348 | .ready = NULL, | ||
| 349 | .is_valid = validate_singlecw_ending, | ||
| 350 | .moveset = &moveset_URF, | ||
| 351 | |||
| 352 | .pre_trans = uf, | ||
| 353 | |||
| 354 | .tables = {&pd_coud_HTM}, | ||
| 355 | .ntables = 1, | ||
| 356 | }; | ||
| 357 | |||
| 358 | Step | ||
| 359 | corl_URF = { | ||
| 360 | .shortname = "corl-URF", | ||
| 361 | .name = "CO on R/L (URF moveset)", | ||
| 362 | |||
| 363 | .final = false, | ||
| 364 | .is_done = check_coud_URF, | ||
| 365 | .estimate = estimate_coud_URF, | ||
| 366 | .ready = NULL, | ||
| 367 | .is_valid = validate_singlecw_ending, | ||
| 368 | .moveset = &moveset_URF, | ||
| 369 | |||
| 370 | .pre_trans = rf, | ||
| 371 | |||
| 372 | .tables = {&pd_coud_HTM}, | ||
| 373 | .ntables = 1, | ||
| 374 | }; | ||
| 375 | |||
| 376 | Step | ||
| 377 | cofb_URF = { | ||
| 378 | .shortname = "cofb-URF", | ||
| 379 | .name = "CO on F/B (URF moveset)", | ||
| 380 | |||
| 381 | .final = false, | ||
| 382 | .is_done = check_coud_URF, | ||
| 383 | .estimate = estimate_coud_URF, | ||
| 384 | .ready = NULL, | ||
| 385 | .is_valid = validate_singlecw_ending, | ||
| 386 | .moveset = &moveset_URF, | ||
| 387 | |||
| 388 | .pre_trans = fd, | ||
| 389 | |||
| 390 | .tables = {&pd_coud_HTM}, | ||
| 391 | .ntables = 1, | ||
| 392 | }; | ||
| 393 | |||
| 394 | /* Misc corner steps *****************/ | ||
| 395 | Step | ||
| 396 | cornershtr_HTM = { | ||
| 397 | .shortname = "chtr", | ||
| 398 | .name = "Solve corners to HTR state", | ||
| 399 | |||
| 400 | .final = false, | ||
| 401 | .is_done = check_cornershtr, | ||
| 402 | .estimate = estimate_cornershtr_HTM, | ||
| 403 | .ready = NULL, | ||
| 404 | .is_valid = validate_singlecw_ending, | ||
| 405 | .moveset = &moveset_HTM, | ||
| 406 | |||
| 407 | .pre_trans = uf, | ||
| 408 | |||
| 409 | .tables = {&pd_cornershtr_HTM}, | ||
| 410 | .ntables = 1, | ||
| 411 | }; | ||
| 412 | |||
| 413 | Step | ||
| 414 | cornershtr_URF = { | ||
| 415 | .shortname = "chtr-URF", | ||
| 416 | .name = "Solve corners to HTR state (URF moveset)", | ||
| 417 | |||
| 418 | .final = false, | ||
| 419 | .is_done = check_cornershtr, | ||
| 420 | .estimate = estimate_cornershtr_URF, | ||
| 421 | .ready = NULL, | ||
| 422 | .is_valid = validate_singlecw_ending, | ||
| 423 | .moveset = &moveset_URF, | ||
| 424 | |||
| 425 | .pre_trans = uf, | ||
| 426 | |||
| 427 | .tables = {&pd_cornershtr_HTM}, | ||
| 428 | .ntables = 1, | ||
| 429 | }; | ||
| 430 | |||
| 431 | Step | ||
| 432 | corners_HTM = { | ||
| 433 | .shortname = "corners", | ||
| 434 | .name = "Solve corners", | ||
| 435 | |||
| 436 | .final = true, | ||
| 437 | .is_done = check_corners_HTM, | ||
| 438 | .estimate = estimate_corners_HTM, | ||
| 439 | .ready = NULL, | ||
| 440 | .is_valid = always_valid, | ||
| 441 | .moveset = &moveset_HTM, | ||
| 442 | |||
| 443 | .pre_trans = uf, | ||
| 444 | |||
| 445 | .tables = {&pd_corners_HTM}, | ||
| 446 | .ntables = 1, | ||
| 447 | }; | ||
| 448 | |||
| 449 | Step | ||
| 450 | corners_URF = { | ||
| 451 | .shortname = "corners-URF", | ||
| 452 | .name = "Solve corners (URF moveset)", | ||
| 453 | |||
| 454 | .final = true, /* TODO: check if this works with reorient */ | ||
| 455 | .is_done = check_corners_URF, | ||
| 456 | .estimate = estimate_corners_URF, | ||
| 457 | .ready = NULL, | ||
| 458 | .is_valid = always_valid, | ||
| 459 | .moveset = &moveset_URF, | ||
| 460 | |||
| 461 | .pre_trans = uf, | ||
| 462 | |||
| 463 | .tables = {&pd_corners_HTM}, | ||
| 464 | .ntables = 1, | ||
| 465 | }; | ||
| 466 | |||
| 467 | /* DR steps **************************/ | ||
| 468 | Step | ||
| 469 | drany_HTM = { | ||
| 470 | .shortname = "dr", | ||
| 471 | .name = "DR on any axis", | ||
| 472 | |||
| 473 | .final = false, | ||
| 474 | .is_done = check_drud, | ||
| 475 | .estimate = estimate_drud_HTM, | ||
| 476 | .ready = check_centers, | ||
| 477 | .ready_msg = check_centers_msg, | ||
| 478 | .is_valid = validate_singlecw_ending, | ||
| 479 | .moveset = &moveset_HTM, | ||
| 480 | |||
| 481 | .detect = detect_pretrans_void_3axis, | ||
| 482 | |||
| 483 | .tables = {&pd_drud_sym16_HTM}, | ||
| 484 | .ntables = 1, | ||
| 485 | }; | ||
| 486 | |||
| 487 | Step | ||
| 488 | drud_HTM = { | ||
| 489 | .shortname = "drud", | ||
| 490 | .name = "DR on U/D", | ||
| 491 | |||
| 492 | .final = false, | ||
| 493 | .is_done = check_drud, | ||
| 494 | .estimate = estimate_drud_HTM, | ||
| 495 | .ready = check_centers, | ||
| 496 | .ready_msg = check_centers_msg, | ||
| 497 | .is_valid = validate_singlecw_ending, | ||
| 498 | .moveset = &moveset_HTM, | ||
| 499 | |||
| 500 | .pre_trans = uf, | ||
| 501 | |||
| 502 | .tables = {&pd_drud_sym16_HTM}, | ||
| 503 | .ntables = 1, | ||
| 504 | }; | ||
| 505 | |||
| 506 | Step | ||
| 507 | drrl_HTM = { | ||
| 508 | .shortname = "drrl", | ||
| 509 | .name = "DR on R/L", | ||
| 510 | |||
| 511 | .final = false, | ||
| 512 | .is_done = check_drud, | ||
| 513 | .estimate = estimate_drud_HTM, | ||
| 514 | .ready = check_centers, | ||
| 515 | .ready_msg = check_centers_msg, | ||
| 516 | .is_valid = validate_singlecw_ending, | ||
| 517 | .moveset = &moveset_HTM, | ||
| 518 | |||
| 519 | .pre_trans = rf, | ||
| 520 | |||
| 521 | .tables = {&pd_drud_sym16_HTM}, | ||
| 522 | .ntables = 1, | ||
| 523 | }; | ||
| 524 | |||
| 525 | Step | ||
| 526 | drfb_HTM = { | ||
| 527 | .shortname = "drfb", | ||
| 528 | .name = "DR on F/B", | ||
| 529 | |||
| 530 | .final = false, | ||
| 531 | .is_done = check_drud, | ||
| 532 | .estimate = estimate_drud_HTM, | ||
| 533 | .ready = check_centers, | ||
| 534 | .ready_msg = check_centers_msg, | ||
| 535 | .is_valid = validate_singlecw_ending, | ||
| 536 | .moveset = &moveset_HTM, | ||
| 537 | |||
| 538 | .pre_trans = fd, | ||
| 539 | |||
| 540 | .tables = {&pd_drud_sym16_HTM}, | ||
| 541 | .ntables = 1, | ||
| 542 | }; | ||
| 543 | |||
| 544 | /* DR from EO */ | ||
| 545 | Step | ||
| 546 | dr_eo = { | ||
| 547 | .shortname = "dr-eo", | ||
| 548 | .name = "DR without breaking EO (automatically detected)", | ||
| 549 | |||
| 550 | .final = false, | ||
| 551 | .is_done = check_drud, | ||
| 552 | .estimate = estimate_dr_eofb, | ||
| 553 | .ready = check_eofb, | ||
| 554 | .ready_msg = check_eo_msg, | ||
| 555 | .is_valid = validate_singlecw_ending, | ||
| 556 | .moveset = &moveset_eofb, | ||
| 557 | |||
| 558 | .detect = detect_pretrans_eofb, | ||
| 559 | |||
| 560 | .tables = {&pd_drud_eofb}, | ||
| 561 | .ntables = 1, | ||
| 562 | }; | ||
| 563 | |||
| 564 | Step | ||
| 565 | dr_eofb = { | ||
| 566 | .shortname = "dr-eofb", | ||
| 567 | .name = "DR on U/D or R/L without breaking EO on F/B", | ||
| 568 | |||
| 569 | .final = false, | ||
| 570 | .is_done = check_drud, | ||
| 571 | .estimate = estimate_dr_eofb, | ||
| 572 | .ready = check_eofb, | ||
| 573 | .ready_msg = check_eo_msg, | ||
| 574 | .is_valid = validate_singlecw_ending, | ||
| 575 | .moveset = &moveset_eofb, | ||
| 576 | |||
| 577 | .pre_trans = uf, | ||
| 578 | |||
| 579 | .tables = {&pd_drud_eofb}, | ||
| 580 | .ntables = 1, | ||
| 581 | }; | ||
| 582 | |||
| 583 | Step | ||
| 584 | dr_eorl = { | ||
| 585 | .shortname = "dr-eorl", | ||
| 586 | .name = "DR on U/D or F/B without breaking EO on R/L", | ||
| 587 | |||
| 588 | .final = false, | ||
| 589 | .is_done = check_drud, | ||
| 590 | .estimate = estimate_dr_eofb, | ||
| 591 | .ready = check_eofb, | ||
| 592 | .ready_msg = check_eo_msg, | ||
| 593 | .is_valid = validate_singlecw_ending, | ||
| 594 | .moveset = &moveset_eofb, | ||
| 595 | |||
| 596 | .pre_trans = ur, | ||
| 597 | |||
| 598 | .tables = {&pd_drud_eofb}, | ||
| 599 | .ntables = 1, | ||
| 600 | }; | ||
| 601 | |||
| 602 | Step | ||
| 603 | dr_eoud = { | ||
| 604 | .shortname = "dr-eoud", | ||
| 605 | .name = "DR on R/L or F/B without breaking EO on U/D", | ||
| 606 | |||
| 607 | .final = false, | ||
| 608 | .is_done = check_drud, | ||
| 609 | .estimate = estimate_dr_eofb, | ||
| 610 | .ready = check_eofb, | ||
| 611 | .ready_msg = check_eo_msg, | ||
| 612 | .is_valid = validate_singlecw_ending, | ||
| 613 | .moveset = &moveset_eofb, | ||
| 614 | |||
| 615 | .pre_trans = fd, | ||
| 616 | |||
| 617 | .tables = {&pd_drud_eofb}, | ||
| 618 | .ntables = 1, | ||
| 619 | }; | ||
| 620 | |||
| 621 | Step | ||
| 622 | drud_eofb = { | ||
| 623 | .shortname = "drud-eofb", | ||
| 624 | .name = "DR on U/D without breaking EO on F/B", | ||
| 625 | |||
| 626 | .final = false, | ||
| 627 | .is_done = check_drud, | ||
| 628 | .estimate = estimate_drud_eofb, | ||
| 629 | .ready = check_eofb, | ||
| 630 | .ready_msg = check_eo_msg, | ||
| 631 | .is_valid = validate_singlecw_ending, | ||
| 632 | .moveset = &moveset_eofb, | ||
| 633 | |||
| 634 | .pre_trans = uf, | ||
| 635 | |||
| 636 | .tables = {&pd_drud_eofb}, | ||
| 637 | .ntables = 1, | ||
| 638 | }; | ||
| 639 | |||
| 640 | Step | ||
| 641 | drrl_eofb = { | ||
| 642 | .shortname = "drrl-eofb", | ||
| 643 | .name = "DR on R/L without breaking EO on F/B", | ||
| 644 | |||
| 645 | .final = false, | ||
| 646 | .is_done = check_drud, | ||
| 647 | .estimate = estimate_drud_eofb, | ||
| 648 | .ready = check_eofb, | ||
| 649 | .ready_msg = check_eo_msg, | ||
| 650 | .is_valid = validate_singlecw_ending, | ||
| 651 | .moveset = &moveset_eofb, | ||
| 652 | |||
| 653 | .pre_trans = rf, | ||
| 654 | |||
| 655 | .tables = {&pd_drud_eofb}, | ||
| 656 | .ntables = 1, | ||
| 657 | }; | ||
| 658 | |||
| 659 | Step | ||
| 660 | drud_eorl = { | ||
| 661 | .shortname = "drud-eorl", | ||
| 662 | .name = "DR on U/D without breaking EO on R/L", | ||
| 663 | |||
| 664 | .final = false, | ||
| 665 | .is_done = check_drud, | ||
| 666 | .estimate = estimate_drud_eofb, | ||
| 667 | .ready = check_eofb, | ||
| 668 | .ready_msg = check_eo_msg, | ||
| 669 | .is_valid = validate_singlecw_ending, | ||
| 670 | .moveset = &moveset_eofb, | ||
| 671 | |||
| 672 | .pre_trans = ur, | ||
| 673 | |||
| 674 | .tables = {&pd_drud_eofb}, | ||
| 675 | .ntables = 1, | ||
| 676 | }; | ||
| 677 | |||
| 678 | Step | ||
| 679 | drfb_eorl = { | ||
| 680 | .shortname = "drfb-eorl", | ||
| 681 | .name = "DR on F/B without breaking EO on R/L", | ||
| 682 | |||
| 683 | .final = false, | ||
| 684 | .is_done = check_drud, | ||
| 685 | .estimate = estimate_drud_eofb, | ||
| 686 | .ready = check_eofb, | ||
| 687 | .ready_msg = check_eo_msg, | ||
| 688 | .is_valid = validate_singlecw_ending, | ||
| 689 | .moveset = &moveset_eofb, | ||
| 690 | |||
| 691 | .pre_trans = fr, | ||
| 692 | |||
| 693 | .tables = {&pd_drud_eofb}, | ||
| 694 | .ntables = 1, | ||
| 695 | }; | ||
| 696 | |||
| 697 | Step | ||
| 698 | drfb_eoud = { | ||
| 699 | .shortname = "drfb-eoud", | ||
| 700 | .name = "DR on F/B without breaking EO on U/D", | ||
| 701 | |||
| 702 | .final = false, | ||
| 703 | .is_done = check_drud, | ||
| 704 | .estimate = estimate_drud_eofb, | ||
| 705 | .ready = check_eofb, | ||
| 706 | .ready_msg = check_eo_msg, | ||
| 707 | .is_valid = validate_singlecw_ending, | ||
| 708 | .moveset = &moveset_eofb, | ||
| 709 | |||
| 710 | .pre_trans = fd, | ||
| 711 | |||
| 712 | .tables = {&pd_drud_eofb}, | ||
| 713 | .ntables = 1, | ||
| 714 | }; | ||
| 715 | |||
| 716 | Step | ||
| 717 | drrl_eoud = { | ||
| 718 | .shortname = "drrl-eoud", | ||
| 719 | .name = "DR on R/L without breaking EO on U/D", | ||
| 720 | |||
| 721 | .final = false, | ||
| 722 | .is_done = check_drud, | ||
| 723 | .estimate = estimate_drud_eofb, | ||
| 724 | .ready = check_eofb, | ||
| 725 | .ready_msg = check_eo_msg, | ||
| 726 | .is_valid = validate_singlecw_ending, | ||
| 727 | .moveset = &moveset_eofb, | ||
| 728 | |||
| 729 | .pre_trans = rd, | ||
| 730 | |||
| 731 | .tables = {&pd_drud_eofb}, | ||
| 732 | .ntables = 1, | ||
| 733 | }; | ||
| 734 | |||
| 735 | /* DR finish steps */ | ||
| 736 | Step | ||
| 737 | dranyfin_DR = { | ||
| 738 | .shortname = "drfin", | ||
| 739 | .name = "DR finish on any axis without breaking DR", | ||
| 740 | |||
| 741 | .final = true, | ||
| 742 | .is_done = is_solved, | ||
| 743 | .estimate = estimate_drudfin_drud, | ||
| 744 | .ready = check_drud, | ||
| 745 | .ready_msg = check_drany_msg, | ||
| 746 | .is_valid = always_valid, | ||
| 747 | .moveset = &moveset_drud, | ||
| 748 | |||
| 749 | .detect = detect_pretrans_drud, | ||
| 750 | |||
| 751 | .tables = {&pd_drudfin_noE_sym16_drud}, | ||
| 752 | .ntables = 1, | ||
| 753 | }; | ||
| 754 | |||
| 755 | Step | ||
| 756 | drudfin_drud = { | ||
| 757 | .shortname = "drudfin", | ||
| 758 | .name = "DR finish on U/D without breaking DR", | ||
| 759 | |||
| 760 | .final = true, | ||
| 761 | .is_done = is_solved, | ||
| 762 | .estimate = estimate_drudfin_drud, | ||
| 763 | .ready = check_drud, | ||
| 764 | .ready_msg = check_dr_msg, | ||
| 765 | .is_valid = always_valid, | ||
| 766 | .moveset = &moveset_drud, | ||
| 767 | |||
| 768 | .pre_trans = uf, | ||
| 769 | |||
| 770 | .tables = {&pd_drudfin_noE_sym16_drud}, | ||
| 771 | .ntables = 1, | ||
| 772 | }; | ||
| 773 | |||
| 774 | Step | ||
| 775 | drrlfin_drrl = { | ||
| 776 | .shortname = "drrlfin", | ||
| 777 | .name = "DR finish on R/L without breaking DR", | ||
| 778 | |||
| 779 | .final = true, | ||
| 780 | .is_done = is_solved, | ||
| 781 | .estimate = estimate_drudfin_drud, | ||
| 782 | .ready = check_drud, | ||
| 783 | .ready_msg = check_dr_msg, | ||
| 784 | .is_valid = always_valid, | ||
| 785 | .moveset = &moveset_drud, | ||
| 786 | |||
| 787 | .pre_trans = rf, | ||
| 788 | |||
| 789 | .tables = {&pd_drudfin_noE_sym16_drud}, | ||
| 790 | .ntables = 1, | ||
| 791 | }; | ||
| 792 | |||
| 793 | Step | ||
| 794 | drfbfin_drfb = { | ||
| 795 | .shortname = "drfbfin", | ||
| 796 | .name = "DR finish on F/B without breaking DR", | ||
| 797 | |||
| 798 | .final = true, | ||
| 799 | .is_done = is_solved, | ||
| 800 | .estimate = estimate_drudfin_drud, | ||
| 801 | .ready = check_drud, | ||
| 802 | .ready_msg = check_dr_msg, | ||
| 803 | .is_valid = always_valid, | ||
| 804 | .moveset = &moveset_drud, | ||
| 805 | |||
| 806 | .pre_trans = fd, | ||
| 807 | |||
| 808 | .tables = {&pd_drudfin_noE_sym16_drud}, | ||
| 809 | .ntables = 1, | ||
| 810 | }; | ||
| 811 | |||
| 812 | /* HTR from DR */ | ||
| 813 | Step | ||
| 814 | htr_any = { | ||
| 815 | .shortname = "htr", | ||
| 816 | .name = "HTR from DR", | ||
| 817 | |||
| 818 | .final = false, | ||
| 819 | .is_done = check_htr, | ||
| 820 | .estimate = estimate_htr_drud, | ||
| 821 | .ready = check_drud, | ||
| 822 | .ready_msg = check_drany_msg, | ||
| 823 | .is_valid = validate_singlecw_ending, | ||
| 824 | .moveset = &moveset_drud, | ||
| 825 | 2 | ||
| 826 | .detect = detect_pretrans_drud, | 3 | #include "steps.h" |
| 827 | |||
| 828 | .tables = {&pd_htr_drud}, | ||
| 829 | .ntables = 1, | ||
| 830 | }; | ||
| 831 | |||
| 832 | Step | ||
| 833 | htr_drud = { | ||
| 834 | .shortname = "htr-drud", | ||
| 835 | .name = "HTR from DR on U/D", | ||
| 836 | |||
| 837 | .final = false, | ||
| 838 | .is_done = check_htr, | ||
| 839 | .estimate = estimate_htr_drud, | ||
| 840 | .ready = check_drud, | ||
| 841 | .ready_msg = check_dr_msg, | ||
| 842 | .is_valid = validate_singlecw_ending, | ||
| 843 | .moveset = &moveset_drud, | ||
| 844 | |||
| 845 | .pre_trans = uf, | ||
| 846 | |||
| 847 | .tables = {&pd_htr_drud}, | ||
| 848 | .ntables = 1, | ||
| 849 | }; | ||
| 850 | |||
| 851 | Step | ||
| 852 | htr_drrl = { | ||
| 853 | .shortname = "htr-drrl", | ||
| 854 | .name = "HTR from DR on R/L", | ||
| 855 | |||
| 856 | .final = false, | ||
| 857 | .is_done = check_htr, | ||
| 858 | .estimate = estimate_htr_drud, | ||
| 859 | .ready = check_drud, | ||
| 860 | .ready_msg = check_dr_msg, | ||
| 861 | .is_valid = validate_singlecw_ending, | ||
| 862 | .moveset = &moveset_drud, | ||
| 863 | |||
| 864 | .pre_trans = rf, | ||
| 865 | |||
| 866 | .tables = {&pd_htr_drud}, | ||
| 867 | .ntables = 1, | ||
| 868 | }; | ||
| 869 | |||
| 870 | Step | ||
| 871 | htr_drfb = { | ||
| 872 | .shortname = "htr-drfb", | ||
| 873 | .name = "HTR from DR on F/B", | ||
| 874 | |||
| 875 | .final = false, | ||
| 876 | .is_done = check_htr, | ||
| 877 | .estimate = estimate_htr_drud, | ||
| 878 | .ready = check_drud, | ||
| 879 | .ready_msg = check_dr_msg, | ||
| 880 | .is_valid = validate_singlecw_ending, | ||
| 881 | .moveset = &moveset_drud, | ||
| 882 | |||
| 883 | .pre_trans = fd, | ||
| 884 | |||
| 885 | .tables = {&pd_htr_drud}, | ||
| 886 | .ntables = 1, | ||
| 887 | }; | ||
| 888 | |||
| 889 | /* HTR finish */ | ||
| 890 | Step | ||
| 891 | htrfin_htr = { | ||
| 892 | .shortname = "htrfin", | ||
| 893 | .name = "HTR finish without breaking HTR", | ||
| 894 | |||
| 895 | .final = true, | ||
| 896 | .is_done = is_solved, | ||
| 897 | .estimate = estimate_htrfin_htr, | ||
| 898 | .ready = check_htr, | ||
| 899 | .ready_msg = check_htr_msg, | ||
| 900 | .is_valid = always_valid, | ||
| 901 | .moveset = &moveset_htr, | ||
| 902 | |||
| 903 | .pre_trans = uf, | ||
| 904 | |||
| 905 | .tables = {&pd_htrfin_htr}, | ||
| 906 | .ntables = 1, | ||
| 907 | }; | ||
| 908 | |||
| 909 | Step *steps[] = { | ||
| 910 | &optimal_HTM, /* first is default */ | ||
| 911 | &optimal_light_HTM, | ||
| 912 | |||
| 913 | &eofin_eo, | ||
| 914 | &eofbfin_eofb, | ||
| 915 | &eorlfin_eorl, | ||
| 916 | &eoudfin_eoud, | ||
| 917 | |||
| 918 | &eoany_HTM, | ||
| 919 | &eofb_HTM, | ||
| 920 | &eorl_HTM, | ||
| 921 | &eoud_HTM, | ||
| 922 | |||
| 923 | &coany_HTM, | ||
| 924 | &coud_HTM, | ||
| 925 | &corl_HTM, | ||
| 926 | &cofb_HTM, | ||
| 927 | |||
| 928 | &coany_URF, | ||
| 929 | &coud_URF, | ||
| 930 | &corl_URF, | ||
| 931 | &cofb_URF, | ||
| 932 | |||
| 933 | &drany_HTM, | ||
| 934 | &drud_HTM, | ||
| 935 | &drrl_HTM, | ||
| 936 | &drfb_HTM, | ||
| 937 | |||
| 938 | &dr_eo, | ||
| 939 | &dr_eofb, | ||
| 940 | &dr_eorl, | ||
| 941 | &dr_eoud, | ||
| 942 | &drud_eofb, | ||
| 943 | &drrl_eofb, | ||
| 944 | &drud_eorl, | ||
| 945 | &drfb_eorl, | ||
| 946 | &drfb_eoud, | ||
| 947 | &drrl_eoud, | ||
| 948 | |||
| 949 | &dranyfin_DR, | ||
| 950 | &drudfin_drud, | ||
| 951 | &drrlfin_drrl, | ||
| 952 | &drfbfin_drfb, | ||
| 953 | |||
| 954 | &htr_any, | ||
| 955 | &htr_drud, | ||
| 956 | &htr_drrl, | ||
| 957 | &htr_drfb, | ||
| 958 | |||
| 959 | &htrfin_htr, | ||
| 960 | |||
| 961 | &cornershtr_HTM, | ||
| 962 | &cornershtr_URF, | ||
| 963 | &corners_HTM, | ||
| 964 | &corners_URF, | ||
| 965 | |||
| 966 | NULL | ||
| 967 | }; | ||
| 968 | |||
| 969 | /* Checkers, estimators and validators ***************************************/ | ||
| 970 | |||
| 971 | static bool | ||
| 972 | check_centers(Cube cube) | ||
| 973 | { | ||
| 974 | return cube.cpos == 0; | ||
| 975 | } | ||
| 976 | |||
| 977 | static bool | ||
| 978 | check_coud_HTM(Cube cube) | ||
| 979 | { | ||
| 980 | return cube.coud == 0; | ||
| 981 | } | ||
| 982 | |||
| 983 | static bool | ||
| 984 | check_coud_URF(Cube cube) | ||
| 985 | { | ||
| 986 | Cube c2, c3; | ||
| 987 | |||
| 988 | c2 = apply_move(z, cube); | ||
| 989 | c3 = apply_move(x, cube); | ||
| 990 | 4 | ||
| 991 | return cube.coud == 0 || c2.coud == 0 || c3.coud == 0; | 5 | /* TODO: change all checkers to use coordinates! */ |
| 992 | } | ||
| 993 | 6 | ||
| 994 | static bool | 7 | bool |
| 995 | check_corners_URF(Cube cube) | 8 | check_centers(Cube *cube) |
| 996 | { | 9 | { |
| 997 | Cube c; | 10 | int i; |
| 998 | Trans i; | ||
| 999 | 11 | ||
| 1000 | for (i = 0; i < NROTATIONS; i++) { | 12 | for (i = 0; i < 6; i++) |
| 1001 | c = apply_alg(rotation_alg(i), cube); | 13 | if (cube->xp[i] != i) |
| 1002 | if (c.cp && c.coud) | 14 | return false; |
| 1003 | return true; | ||
| 1004 | } | ||
| 1005 | 15 | ||
| 1006 | return false; | 16 | return true; |
| 1007 | } | 17 | } |
| 1008 | 18 | ||
| 1009 | static bool | 19 | bool |
| 1010 | check_corners_HTM(Cube cube) | 20 | check_coud_HTM(Cube *cube) |
| 1011 | { | 21 | { |
| 1012 | return cube.cp == 0 && cube.coud == 0; | 22 | int i; |
| 1013 | } | ||
| 1014 | 23 | ||
| 1015 | static bool | 24 | for (i = 0; i < 8; i++) |
| 1016 | check_cornershtr(Cube cube) | 25 | if (cube->co[i] != 0) |
| 1017 | { | 26 | return false; |
| 1018 | return coord_cornershtr.index(cube) == 0; | ||
| 1019 | } | ||
| 1020 | 27 | ||
| 1021 | static bool | 28 | return true; |
| 1022 | check_eofb(Cube cube) | ||
| 1023 | { | ||
| 1024 | return cube.eofb == 0; | ||
| 1025 | } | 29 | } |
| 1026 | 30 | ||
| 1027 | static bool | 31 | bool |
| 1028 | check_drud(Cube cube) | 32 | check_coud_URF(Cube *cube) |
| 1029 | { | 33 | { |
| 1030 | return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; | 34 | Cube c2, c3; |
| 1031 | } | ||
| 1032 | 35 | ||
| 1033 | static bool | 36 | copy_cube(cube, &c2); |
| 1034 | check_htr(Cube cube) | 37 | copy_cube(cube, &c3); |
| 1035 | { | ||
| 1036 | return check_drud(cube) && coord_htr_drud.index(cube) == 0; | ||
| 1037 | } | ||
| 1038 | 38 | ||
| 1039 | static int | 39 | apply_move(z, &c2); |
| 1040 | estimate_eofb_HTM(DfsArg *arg) | 40 | apply_move(x, &c3); |
| 1041 | { | ||
| 1042 | return ptableval(&pd_eofb_HTM, arg->cube); | ||
| 1043 | } | ||
| 1044 | 41 | ||
| 1045 | static int | 42 | return check_coud_HTM(cube) || |
| 1046 | estimate_coud_HTM(DfsArg *arg) | 43 | check_coud_HTM(&c2) || |
| 1047 | { | 44 | check_coud_HTM(&c3); |
| 1048 | return ptableval(&pd_coud_HTM, arg->cube); | ||
| 1049 | } | 45 | } |
| 1050 | 46 | ||
| 1051 | static int | 47 | bool |
| 1052 | estimate_coud_URF(DfsArg *arg) | 48 | check_cp_HTM(Cube *cube) |
| 1053 | { | 49 | { |
| 1054 | /* TODO: I can improve this by checking first the orientation of | 50 | int i; |
| 1055 | * the corner in DBL and use that as a reference */ | ||
| 1056 | |||
| 1057 | Cube c; | ||
| 1058 | |||
| 1059 | c = arg->cube; | ||
| 1060 | |||
| 1061 | int ud = estimate_coud_HTM(arg); | ||
| 1062 | arg->cube = apply_move(z, c); | ||
| 1063 | int rl = estimate_coud_HTM(arg); | ||
| 1064 | arg->cube = apply_move(x, c); | ||
| 1065 | int fb = estimate_coud_HTM(arg); | ||
| 1066 | |||
| 1067 | arg->cube = c; | ||
| 1068 | 51 | ||
| 1069 | return MIN(ud, MIN(rl, fb)); | 52 | for (i = 0; i < 8; i++) |
| 1070 | } | 53 | if (cube->cp[i] != i) |
| 54 | return false; | ||
| 1071 | 55 | ||
| 1072 | static int | 56 | return true; |
| 1073 | estimate_corners_HTM(DfsArg *arg) | ||
| 1074 | { | ||
| 1075 | return ptableval(&pd_corners_HTM, arg->cube); | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | static int | ||
| 1079 | estimate_cornershtr_HTM(DfsArg *arg) | ||
| 1080 | { | ||
| 1081 | return ptableval(&pd_cornershtr_HTM, arg->cube); | ||
| 1082 | } | 57 | } |
| 1083 | 58 | ||
| 1084 | static int | 59 | bool |
| 1085 | estimate_cornershtr_URF(DfsArg *arg) | 60 | check_corners_HTM(Cube *cube) |
| 1086 | { | 61 | { |
| 1087 | /* TODO: I can improve this by checking first the corner in DBL | 62 | return check_coud_HTM(cube) && check_cp_HTM(cube); |
| 1088 | * and use that as a reference */ | ||
| 1089 | |||
| 1090 | int ret; | ||
| 1091 | Cube c; | ||
| 1092 | Trans i; | ||
| 1093 | |||
| 1094 | c = arg->cube; | ||
| 1095 | ret = 15; | ||
| 1096 | |||
| 1097 | for (i = 0; i < NROTATIONS; i++) { | ||
| 1098 | arg->cube = apply_alg(rotation_alg(i), c); | ||
| 1099 | ret = MIN(ret, estimate_cornershtr_HTM(arg)); | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | arg->cube = c; | ||
| 1103 | |||
| 1104 | return ret; | ||
| 1105 | } | 63 | } |
| 1106 | 64 | ||
| 1107 | static int | 65 | bool |
| 1108 | estimate_corners_URF(DfsArg *arg) | 66 | check_corners_URF(Cube *cube) |
| 1109 | { | 67 | { |
| 1110 | /* TODO: I can improve this by checking first the corner in DBL | ||
| 1111 | * and use that as a reference */ | ||
| 1112 | |||
| 1113 | int ret; | ||
| 1114 | Cube c; | 68 | Cube c; |
| 1115 | Trans i; | 69 | Trans i; |
| 1116 | 70 | ||
| 1117 | c = arg->cube; | ||
| 1118 | ret = 15; | ||
| 1119 | |||
| 1120 | for (i = 0; i < NROTATIONS; i++) { | 71 | for (i = 0; i < NROTATIONS; i++) { |
| 1121 | arg->cube = apply_alg(rotation_alg(i), c); | 72 | copy_cube(cube, &c); |
| 1122 | ret = MIN(ret, estimate_corners_HTM(arg)); | 73 | apply_alg(rotation_alg(i), &c); |
| 74 | if (check_corners_HTM(&c)) | ||
| 75 | return true; | ||
| 1123 | } | 76 | } |
| 1124 | 77 | ||
| 1125 | arg->cube = c; | 78 | return false; |
| 1126 | |||
| 1127 | return ret; | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | static int | ||
| 1131 | estimate_drud_HTM(DfsArg *arg) | ||
| 1132 | { | ||
| 1133 | return ptableval(&pd_drud_sym16_HTM, arg->cube); | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | static int | ||
| 1137 | estimate_drud_eofb(DfsArg *arg) | ||
| 1138 | { | ||
| 1139 | return ptableval(&pd_drud_eofb, arg->cube); | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | static int | ||
| 1143 | estimate_dr_eofb(DfsArg *arg) | ||
| 1144 | { | ||
| 1145 | int r1, r2; | ||
| 1146 | |||
| 1147 | r1 = ptableval(&pd_drud_eofb, arg->cube); | ||
| 1148 | r2 = ptableval(&pd_drud_eofb, apply_trans(rf, arg->cube)); | ||
| 1149 | |||
| 1150 | return MIN(r1, r2); | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | static int | ||
| 1154 | estimate_drudfin_drud(DfsArg *arg) | ||
| 1155 | { | ||
| 1156 | int val = ptableval(&pd_drudfin_noE_sym16_drud, arg->cube); | ||
| 1157 | |||
| 1158 | if (val != 0) | ||
| 1159 | return val; | ||
| 1160 | |||
| 1161 | return arg->cube.epose % 24 == 0 ? 0 : 1; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | static int | ||
| 1165 | estimate_htr_drud(DfsArg *arg) | ||
| 1166 | { | ||
| 1167 | return ptableval(&pd_htr_drud, arg->cube); | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | static int | ||
| 1171 | estimate_htrfin_htr(DfsArg *arg) | ||
| 1172 | { | ||
| 1173 | return ptableval(&pd_htrfin_htr, arg->cube); | ||
| 1174 | } | 79 | } |
| 1175 | 80 | ||
| 1176 | static int | 81 | bool |
| 1177 | estimate_nxopt31_HTM(DfsArg *arg) | 82 | check_cornershtr(Cube *cube) |
| 1178 | { | 83 | { |
| 1179 | return estimate_nxoptlike(arg, &pd_nxopt31_HTM); | 84 | /* TODO (use coord) */ |
| 85 | return true; | ||
| 1180 | } | 86 | } |
| 1181 | 87 | ||
| 1182 | /* TODO: also use generic procedure for this */ | 88 | bool |
| 1183 | static int | 89 | check_eofb(Cube *cube) |
| 1184 | estimate_light_HTM(DfsArg *arg) | ||
| 1185 | { | 90 | { |
| 1186 | int target, ret; | 91 | /* TODO (use coord) */ |
| 1187 | Cube aux; | 92 | return true; |
| 1188 | |||
| 1189 | static const uint64_t udmask = (1<<U) | (1<<U2) | (1<<U3) | | ||
| 1190 | (1<<D) | (1<<D2) | (1<<D3); | ||
| 1191 | static const uint64_t rlmask = (1<<R) | (1<<R2) | (1<<R3) | | ||
| 1192 | (1<<L) | (1<<L2) | (1<<L3); | ||
| 1193 | static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) | | ||
| 1194 | (1<<B) | (1<<B2) | (1<<B3); | ||
| 1195 | static const uint64_t htmask = (1<<U2) | (1<<D2) | | ||
| 1196 | (1<<R2) | (1<<L2) | | ||
| 1197 | (1<<F2) | (1<<B2); | ||
| 1198 | |||
| 1199 | ret = -1; | ||
| 1200 | target = arg->d - arg->current_alg->len; | ||
| 1201 | arg->inverse = (Cube){0}; | ||
| 1202 | arg->badmovesinv = 0; | ||
| 1203 | arg->badmoves = 0; | ||
| 1204 | |||
| 1205 | /* Corners */ | ||
| 1206 | arg->ed->corners = ptableval(&pd_corners_HTM, arg->cube); | ||
| 1207 | UPDATECHECKSTOP(ret, arg->ed->corners, target); | ||
| 1208 | |||
| 1209 | /* Normal probing */ | ||
| 1210 | arg->ed->normal_ud = ptableval(&pd_drud_sym16_HTM, arg->cube); | ||
| 1211 | UPDATECHECKSTOP(ret, arg->ed->normal_ud, target); | ||
| 1212 | aux = apply_trans(fd, arg->cube); | ||
| 1213 | arg->ed->normal_fb = ptableval(&pd_drud_sym16_HTM, aux); | ||
| 1214 | UPDATECHECKSTOP(ret, arg->ed->normal_fb, target); | ||
| 1215 | aux = apply_trans(rf, arg->cube); | ||
| 1216 | arg->ed->normal_rl = ptableval(&pd_drud_sym16_HTM, aux); | ||
| 1217 | UPDATECHECKSTOP(ret, arg->ed->normal_rl, target); | ||
| 1218 | |||
| 1219 | /* If ret == 0, it's solved (corners + triple slice solved) */ | ||
| 1220 | if (ret == 0) | ||
| 1221 | return is_solved(arg->cube) ? 0 : 1; | ||
| 1222 | |||
| 1223 | /* Michel de Bondt's trick*/ | ||
| 1224 | if (arg->ed->normal_ud == arg->ed->normal_fb && | ||
| 1225 | arg->ed->normal_fb == arg->ed->normal_rl) { | ||
| 1226 | UPDATECHECKSTOP(ret, arg->ed->normal_ud + 1, target); | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | /* Inverse probing */ | ||
| 1230 | if (!((1<<arg->last1) & htmask)) { | ||
| 1231 | aux = arg->inverse = inverse_cube(arg->cube); | ||
| 1232 | if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud==-1)) { | ||
| 1233 | arg->ed->inverse_ud = | ||
| 1234 | ptableval(&pd_drud_sym16_HTM, aux); | ||
| 1235 | } | ||
| 1236 | UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); | ||
| 1237 | if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb==-1)) { | ||
| 1238 | aux = apply_trans(fd, arg->inverse); | ||
| 1239 | arg->ed->inverse_fb = | ||
| 1240 | ptableval(&pd_drud_sym16_HTM, aux); | ||
| 1241 | } | ||
| 1242 | UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); | ||
| 1243 | if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl==-1)) { | ||
| 1244 | aux = apply_trans(rf, arg->inverse); | ||
| 1245 | arg->ed->inverse_rl = | ||
| 1246 | ptableval(&pd_drud_sym16_HTM, aux); | ||
| 1247 | } | ||
| 1248 | UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); | ||
| 1249 | } else { | ||
| 1250 | UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); | ||
| 1251 | UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); | ||
| 1252 | UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); | ||
| 1253 | } | ||
| 1254 | |||
| 1255 | /* Michel de Bondt's trick*/ | ||
| 1256 | if (arg->ed->inverse_ud == arg->ed->inverse_fb && | ||
| 1257 | arg->ed->inverse_fb == arg->ed->inverse_rl) { | ||
| 1258 | UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target); | ||
| 1259 | } | ||
| 1260 | |||
| 1261 | /* nxopt trick + half turn trick */ | ||
| 1262 | if (arg->ed->normal_ud == target) | ||
| 1263 | arg->badmovesinv |= udmask | htmask; | ||
| 1264 | if (arg->ed->normal_fb == target) | ||
| 1265 | arg->badmovesinv |= fbmask | htmask; | ||
| 1266 | if (arg->ed->normal_rl == target) | ||
| 1267 | arg->badmovesinv |= rlmask | htmask; | ||
| 1268 | |||
| 1269 | if (arg->ed->inverse_ud == target) | ||
| 1270 | arg->badmoves |= udmask | htmask; | ||
| 1271 | if (arg->ed->inverse_fb == target) | ||
| 1272 | arg->badmoves |= fbmask | htmask; | ||
| 1273 | if (arg->ed->inverse_rl == target) | ||
| 1274 | arg->badmoves |= rlmask | htmask; | ||
| 1275 | |||
| 1276 | return arg->ed->oldret = ret; | ||
| 1277 | } | 93 | } |
| 1278 | 94 | ||
| 1279 | static int | 95 | bool |
| 1280 | estimate_nxoptlike(DfsArg *arg, PruneData *pd) | 96 | check_drud(Cube *cube) |
| 1281 | { | 97 | { |
| 1282 | int target, ret; | 98 | /* TODO (use coord) */ |
| 1283 | Cube aux; | 99 | return true; |
| 1284 | |||
| 1285 | static const uint64_t udmask = (1<<U) | (1<<U2) | (1<<U3) | | ||
| 1286 | (1<<D) | (1<<D2) | (1<<D3); | ||
| 1287 | static const uint64_t rlmask = (1<<R) | (1<<R2) | (1<<R3) | | ||
| 1288 | (1<<L) | (1<<L2) | (1<<L3); | ||
| 1289 | static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) | | ||
| 1290 | (1<<B) | (1<<B2) | (1<<B3); | ||
| 1291 | |||
| 1292 | ret = -1; | ||
| 1293 | target = arg->d - arg->current_alg->len; | ||
| 1294 | arg->inverse = (Cube){0}; | ||
| 1295 | arg->badmovesinv = 0; | ||
| 1296 | arg->badmoves = 0; | ||
| 1297 | |||
| 1298 | /* Corners */ | ||
| 1299 | arg->ed->corners = ptableval(&pd_corners_HTM, arg->cube); | ||
| 1300 | UPDATECHECKSTOP(ret, arg->ed->corners, target); | ||
| 1301 | |||
| 1302 | /* Normal probing */ | ||
| 1303 | arg->ed->normal_ud = ptableval(pd, arg->cube); | ||
| 1304 | UPDATECHECKSTOP(ret, arg->ed->normal_ud, target); | ||
| 1305 | aux = apply_trans(fd, arg->cube); | ||
| 1306 | arg->ed->normal_fb = ptableval(pd, aux); | ||
| 1307 | UPDATECHECKSTOP(ret, arg->ed->normal_fb, target); | ||
| 1308 | aux = apply_trans(rf, arg->cube); | ||
| 1309 | arg->ed->normal_rl = ptableval(pd, aux); | ||
| 1310 | UPDATECHECKSTOP(ret, arg->ed->normal_rl, target); | ||
| 1311 | |||
| 1312 | if (ret == 0) | ||
| 1313 | return arg->step->is_done(arg->cube) ? 0 : 1; | ||
| 1314 | |||
| 1315 | /* Michel de Bondt's trick*/ | ||
| 1316 | if (arg->ed->normal_ud == arg->ed->normal_fb && | ||
| 1317 | arg->ed->normal_fb == arg->ed->normal_rl) { | ||
| 1318 | UPDATECHECKSTOP(ret, arg->ed->normal_ud + 1, target); | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | /* Inverse probing */ | ||
| 1322 | aux = arg->inverse = inverse_cube(arg->cube); | ||
| 1323 | if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud == -1)) { | ||
| 1324 | arg->ed->inverse_ud = ptableval(pd, aux); | ||
| 1325 | } | ||
| 1326 | UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); | ||
| 1327 | if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb == -1)) { | ||
| 1328 | aux = apply_trans(fd, arg->inverse); | ||
| 1329 | arg->ed->inverse_fb = ptableval(pd, aux); | ||
| 1330 | } | ||
| 1331 | UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); | ||
| 1332 | if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl == -1)) { | ||
| 1333 | aux = apply_trans(rf, arg->inverse); | ||
| 1334 | arg->ed->inverse_rl = ptableval(pd, aux); | ||
| 1335 | } | ||
| 1336 | UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); | ||
| 1337 | |||
| 1338 | /* Michel de Bondt's trick*/ | ||
| 1339 | if (arg->ed->inverse_ud == arg->ed->inverse_fb && | ||
| 1340 | arg->ed->inverse_fb == arg->ed->inverse_rl) { | ||
| 1341 | UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target); | ||
| 1342 | } | ||
| 1343 | |||
| 1344 | /* nxopt trick */ | ||
| 1345 | if (arg->ed->normal_ud == target) | ||
| 1346 | arg->badmovesinv |= udmask; | ||
| 1347 | if (arg->ed->normal_fb == target) | ||
| 1348 | arg->badmovesinv |= fbmask; | ||
| 1349 | if (arg->ed->normal_rl == target) | ||
| 1350 | arg->badmovesinv |= rlmask; | ||
| 1351 | |||
| 1352 | if (arg->ed->inverse_ud == target) | ||
| 1353 | arg->badmoves |= udmask; | ||
| 1354 | if (arg->ed->inverse_fb == target) | ||
| 1355 | arg->badmoves |= fbmask; | ||
| 1356 | if (arg->ed->inverse_rl == target) | ||
| 1357 | arg->badmoves |= rlmask; | ||
| 1358 | |||
| 1359 | return arg->ed->oldret = ret; | ||
| 1360 | } | 100 | } |
| 1361 | 101 | ||
| 1362 | 102 | bool | |
| 1363 | static bool | 103 | check_htr(Cube *cube) |
| 1364 | always_valid(Alg *alg) | ||
| 1365 | { | 104 | { |
| 105 | /* TODO (check_drud(cube) and coord_htr_drud == 0) */ | ||
| 1366 | return true; | 106 | return true; |
| 1367 | } | 107 | } |
| 1368 | 108 | ||
| 1369 | static bool | 109 | bool |
| 1370 | validate_singlecw_ending(Alg *alg) | 110 | validate_singlecw_ending(Alg *alg) |
| 1371 | { | 111 | { |
| 1372 | int i; | 112 | int i; |
| @@ -1389,93 +129,93 @@ validate_singlecw_ending(Alg *alg) | |||
| 1389 | return nor && inv; | 129 | return nor && inv; |
| 1390 | } | 130 | } |
| 1391 | 131 | ||
| 1392 | /* Pre-transformation detectors **********************************************/ | 132 | /* Public functions **********************************************************/ |
| 1393 | 133 | ||
| 1394 | static int | 134 | void |
| 1395 | detect_pretrans_eofb(Cube cube, Trans *ret) | 135 | compute_ind(StepAlt *a, Cube *cube, Movable *ind) |
| 1396 | { | 136 | { |
| 1397 | int i, n; | 137 | int i; |
| 1398 | static Trans tt[3] = {uf, ur, fd}; | 138 | Cube mvd; |
| 139 | Trans t, tt; | ||
| 1399 | 140 | ||
| 1400 | for (i = 0, n = 0; i < 3; i++) | 141 | for (i = 0; i < a->n_coord; i++) { |
| 1401 | if (check_eofb(apply_trans(tt[i], cube))) | 142 | t = a->coord_trans[i]; |
| 1402 | ret[n++] = tt[i]; | 143 | copy_cube(cube, &mvd); |
| 144 | apply_trans(t, &mvd); | ||
| 1403 | 145 | ||
| 1404 | return n; | 146 | ind[i].val = index_coord(a->coord[i], &mvd, &tt); |
| 147 | ind[i].t = transform_trans(tt, t); | ||
| 148 | } | ||
| 1405 | } | 149 | } |
| 1406 | 150 | ||
| 1407 | static int | 151 | int |
| 1408 | detect_pretrans_drud(Cube cube, Trans *ret) | 152 | estimate_stepalt(StepAlt *a, Movable *ind, int goal) |
| 1409 | { | 153 | { |
| 1410 | int i, n; | 154 | int i, ret, est[a->n_coord]; |
| 1411 | static Trans tt[3] = {uf, fr, rd}; | ||
| 1412 | 155 | ||
| 1413 | for (i = 0, n = 0; i < 3; i++) | 156 | for (i = 0; i < a->n_coord; i++) { |
| 1414 | if (check_drud(apply_trans(tt[i], cube))) | 157 | est[i] = ptableval(a->pd[i], ind[i].val); |
| 1415 | ret[n++] = tt[i]; | 158 | if (est[i] == a->pd[i]->base && a->compact_pd[i]) |
| 159 | est[i] = ptableval(a->fallback_pd[i], | ||
| 160 | ind[i].val/a->fbmod[i]); | ||
| 161 | if (ind[i].val != 0 && est[i] == 0) /* est == 0 iff solved */ | ||
| 162 | est[i] = 1; | ||
| 163 | /* | ||
| 164 | TODO: remove this debug code | ||
| 165 | printf("%d: est=%d | ", i, est[i]); | ||
| 166 | */ | ||
| 1416 | 167 | ||
| 1417 | return n; | 168 | if (est[i] > goal) |
| 1418 | } | 169 | return est[i]; |
| 170 | } | ||
| 1419 | 171 | ||
| 1420 | static int | 172 | for (i = 0; i < a->n_dbtrick; i++) |
| 1421 | detect_pretrans_void_3axis(Cube cube, Trans *ret) | 173 | if (est[a->dbtrick[i][0]] > 0 && |
| 1422 | { | 174 | est[a->dbtrick[i][0]] == est[a->dbtrick[i][1]] && |
| 1423 | ret[0] = uf; | 175 | est[a->dbtrick[i][0]] == est[a->dbtrick[i][2]]) |
| 1424 | ret[1] = fr; | 176 | est[a->dbtrick[i][0]] += 1; |
| 1425 | ret[2] = rd; | ||
| 1426 | 177 | ||
| 1427 | return 3; | 178 | for (i = 0, ret = -1; i < a->n_coord; i++) |
| 1428 | } | 179 | ret = MAX(ret, est[i]); |
| 1429 | 180 | ||
| 1430 | /* Public functions **********************************************************/ | 181 | /* |
| 182 | TODO: remove this debug code | ||
| 183 | printf("Final estimate: %d\n", ret); | ||
| 184 | */ | ||
| 1431 | 185 | ||
| 1432 | void | 186 | return ret; |
| 1433 | copy_estimatedata(EstimateData *src, EstimateData *dst) | ||
| 1434 | { | ||
| 1435 | dst->corners = src->corners; | ||
| 1436 | dst->normal_ud = src->normal_ud; | ||
| 1437 | dst->normal_fb = src->normal_fb; | ||
| 1438 | dst->normal_rl = src->normal_rl; | ||
| 1439 | dst->inverse_ud = src->inverse_ud; | ||
| 1440 | dst->inverse_fb = src->inverse_fb; | ||
| 1441 | dst->inverse_rl = src->inverse_rl; | ||
| 1442 | dst->oldret = src->oldret; | ||
| 1443 | } | 187 | } |
| 1444 | 188 | ||
| 1445 | void | 189 | void |
| 1446 | invert_estimatedata(EstimateData *ed) | 190 | prepare_step(Step *step, SolveOptions *opts) |
| 1447 | { | 191 | { |
| 1448 | swap(&(ed->normal_ud), &(ed->inverse_ud)); | 192 | int i, j; |
| 1449 | swap(&(ed->normal_fb), &(ed->inverse_fb)); | 193 | PDGenData pdg; |
| 1450 | swap(&(ed->normal_rl), &(ed->inverse_rl)); | 194 | StepAlt *a; |
| 1451 | } | ||
| 1452 | 195 | ||
| 1453 | void | 196 | for (i = 0; step->alt[i] != NULL; i++) { |
| 1454 | reset_estimatedata(EstimateData *ed) | 197 | a = step->alt[i]; |
| 1455 | { | 198 | init_moveset(a->moveset); |
| 1456 | ed->corners = -1; | 199 | pdg.moveset = a->moveset; |
| 1457 | ed->normal_ud = -1; | 200 | for (j = 0; j < a->n_coord; j++) { |
| 1458 | ed->normal_fb = -1; | 201 | gen_coord(a->coord[j]); |
| 1459 | ed->normal_rl = -1; | ||
| 1460 | ed->inverse_ud = -1; | ||
| 1461 | ed->inverse_fb = -1; | ||
| 1462 | ed->inverse_rl = -1; | ||
| 1463 | ed->oldret = -1; | ||
| 1464 | } | ||
| 1465 | 202 | ||
| 1466 | void | 203 | pdg.coord = a->coord[j]; |
| 1467 | prepare_step(Step *step, SolveOptions *opts) | 204 | pdg.compact = a->compact_pd[j]; |
| 1468 | { | 205 | pdg.pd = NULL; |
| 1469 | int i; | ||
| 1470 | 206 | ||
| 1471 | if (step->final && opts->can_niss) { | 207 | a->pd[j] = genptable(&pdg, opts->nthreads); |
| 1472 | opts->can_niss = false; | 208 | |
| 1473 | fprintf(stderr, "Step is final, NISS not used (-n ignored)\n"); | 209 | if (a->compact_pd[j]) { |
| 1474 | } | 210 | gen_coord(a->fallback_coord[j]); |
| 1475 | 211 | ||
| 1476 | for (i = 0; i < step->ntables; i++) { | 212 | pdg.coord = a->fallback_coord[j]; |
| 1477 | genptable(step->tables[i], opts->nthreads); | 213 | pdg.compact = false; |
| 1478 | if (step->tables[i]->compact) | 214 | pdg.pd = NULL; |
| 1479 | genptable(step->tables[i]->fallback, opts->nthreads); | 215 | |
| 216 | a->fallback_pd[j] = | ||
| 217 | genptable(&pdg, opts->nthreads); | ||
| 218 | } | ||
| 219 | } | ||
| 1480 | } | 220 | } |
| 1481 | } | 221 | } |
diff --git a/src/steps.h b/src/steps.h index da5c041..341be98 100644 --- a/src/steps.h +++ b/src/steps.h | |||
| @@ -3,15 +3,275 @@ | |||
| 3 | 3 | ||
| 4 | #include "pruning.h" | 4 | #include "pruning.h" |
| 5 | 5 | ||
| 6 | extern Step * steps[]; | 6 | bool check_centers(Cube *cube); |
| 7 | bool check_coud_HTM(Cube *cube); | ||
| 8 | bool check_coud_URF(Cube *cube); | ||
| 9 | bool check_cp_HTM(Cube *cube); | ||
| 10 | bool check_corners_HTM(Cube *cube); | ||
| 11 | bool check_corners_URF(Cube *cube); | ||
| 12 | bool check_cornershtr(Cube *cube); | ||
| 13 | bool check_eofb(Cube *cube); | ||
| 14 | bool check_drud(Cube *cube); | ||
| 15 | bool check_htr(Cube *cube); | ||
| 16 | void compute_ind(StepAlt *a, Cube *cube, Movable *ind); | ||
| 17 | int estimate_stepalt(StepAlt *a, Movable *ind, int goal); | ||
| 18 | void prepare_step(Step *step, SolveOptions *opts); | ||
| 19 | bool always_valid(Alg *alg); | ||
| 20 | bool validate_singlecw_ending(Alg *alg); | ||
| 7 | 21 | ||
| 8 | /* Two steps used directly by two-phase solver */ | 22 | #ifndef STEPS_C |
| 9 | extern Step drany_HTM; | ||
| 10 | extern Step dranyfin_DR; | ||
| 11 | 23 | ||
| 12 | void copy_estimatedata(EstimateData *s, EstimateData *d); | 24 | extern char check_centers_msg[100]; |
| 13 | void invert_estimatedata(EstimateData *ed); | 25 | extern char check_eo_msg[100]; |
| 14 | void reset_estimatedata(EstimateData *ed); | 26 | extern char check_dr_msg[100]; |
| 15 | void prepare_step(Step *step, SolveOptions *opts); | 27 | extern char check_htr_msg[100]; |
| 28 | extern char check_drany_msg[100]; | ||
| 29 | |||
| 30 | extern StepAlt sa_nxopt31_HTM; | ||
| 31 | extern StepAlt sa_eofb_HTM; | ||
| 32 | extern StepAlt sa_drud_HTM; | ||
| 33 | extern StepAlt sa_drfin_drud; | ||
| 34 | |||
| 35 | extern Step optimal_HTM; | ||
| 36 | extern Step eoany_HTM; | ||
| 37 | extern Step eofb_HTM; | ||
| 38 | extern Step eorl_HTM; | ||
| 39 | extern Step eoud_HTM; | ||
| 40 | extern Step drany_HTM; | ||
| 41 | extern Step drud_HTM; | ||
| 42 | extern Step drrl_HTM; | ||
| 43 | extern Step drfb_HTM; | ||
| 44 | extern Step dranyfin_DR; | ||
| 45 | extern Step drudfin_drud; | ||
| 46 | extern Step drrlfin_drrl; | ||
| 47 | extern Step drfbfin_drfb; | ||
| 48 | |||
| 49 | extern Step *steps[]; | ||
| 50 | |||
| 51 | #else | ||
| 52 | |||
| 53 | char check_centers_msg[100] = "cube must be oriented (centers solved)"; | ||
| 54 | char check_eo_msg[100] = "EO must be solved on given axis"; | ||
| 55 | char check_dr_msg[100] = "DR must be solved on given axis"; | ||
| 56 | char check_htr_msg[100] = "HTR must be solved"; | ||
| 57 | char check_drany_msg[100] = "DR must be solved on at least one axis"; | ||
| 58 | |||
| 59 | /* Optimal solvers *******************/ | ||
| 60 | /* TODO: build options for smaller optimal solvers */ | ||
| 61 | |||
| 62 | StepAlt | ||
| 63 | sa_nxopt31_HTM = { | ||
| 64 | .ready = check_centers, | ||
| 65 | .final = true, | ||
| 66 | .moveset = &moveset_HTM, | ||
| 67 | .n_coord = 6, | ||
| 68 | .coord = {&coord_nxopt31, &coord_nxopt31, &coord_nxopt31, | ||
| 69 | &coord_eposepe, &coord_eposepe, &coord_eposepe}, | ||
| 70 | /* TODO: use khuge as fallback? */ | ||
| 71 | .coord_trans = {uf, rd, bl, uf, rd, bl}, | ||
| 72 | .compact_pd = {true, true, true, false, false, false}, | ||
| 73 | .fallback_coord = {&coord_drud_sym16, &coord_drud_sym16, | ||
| 74 | &coord_drud_sym16}, | ||
| 75 | .fbmod = {BINOM8ON4, BINOM8ON4, BINOM8ON4}, | ||
| 76 | .n_dbtrick = 1, /* TODO: change to 2 when khuge */ | ||
| 77 | .dbtrick = {{0, 1, 2}}, | ||
| 78 | .is_valid = NULL, | ||
| 79 | }; | ||
| 80 | Step | ||
| 81 | optimal_HTM = { | ||
| 82 | .shortname = "optimal", | ||
| 83 | .name = "Optimal solve (in HTM)", | ||
| 84 | .alt = {&sa_nxopt31_HTM, NULL}, | ||
| 85 | .t = {uf}, | ||
| 86 | .ready_msg = check_centers_msg, | ||
| 87 | }; | ||
| 88 | |||
| 89 | /* Optimal after EO ******************/ | ||
| 90 | /* TODO: eofin_eo (generic), eofbfin_eofb, eorlfin_eorl, eoudfin_eoud */ | ||
| 91 | |||
| 92 | /* EO steps **************************/ | ||
| 93 | /* TODO: eoany_HTM (generic), eofb_HTM, eorl_HTM, eoud_HTM */ | ||
| 94 | |||
| 95 | StepAlt | ||
| 96 | sa_eofb_HTM = { | ||
| 97 | .ready = check_centers, | ||
| 98 | .final = false, | ||
| 99 | .moveset = &moveset_HTM, | ||
| 100 | .n_coord = 1, | ||
| 101 | .coord = {&coord_eofb}, | ||
| 102 | .coord_trans = {uf}, | ||
| 103 | .compact_pd = {false}, | ||
| 104 | .n_dbtrick = 0, | ||
| 105 | .is_valid = validate_singlecw_ending, | ||
| 106 | }; | ||
| 107 | Step | ||
| 108 | eoany_HTM = { | ||
| 109 | .shortname = "eo", | ||
| 110 | .name = "EO on any axis", | ||
| 111 | .alt = {&sa_eofb_HTM, &sa_eofb_HTM, &sa_eofb_HTM, NULL}, | ||
| 112 | .t = {uf, ur, fd}, | ||
| 113 | .ready_msg = check_centers_msg, | ||
| 114 | }; | ||
| 115 | Step | ||
| 116 | eofb_HTM = { | ||
| 117 | .shortname = "eofb", | ||
| 118 | .name = "EO on F/B", | ||
| 119 | .alt = {&sa_eofb_HTM, NULL}, | ||
| 120 | .t = {uf}, | ||
| 121 | .ready_msg = check_centers_msg, | ||
| 122 | }; | ||
| 123 | Step | ||
| 124 | eorl_HTM = { | ||
| 125 | .shortname = "eorl", | ||
| 126 | .name = "EO on R/L", | ||
| 127 | .alt = {&sa_eofb_HTM, NULL}, | ||
| 128 | .t = {ur}, | ||
| 129 | .ready_msg = check_centers_msg, | ||
| 130 | }; | ||
| 131 | Step | ||
| 132 | eoud_HTM = { | ||
| 133 | .shortname = "eoud", | ||
| 134 | .name = "EO on U/D", | ||
| 135 | .alt = {&sa_eofb_HTM, NULL}, | ||
| 136 | .t = {fd}, | ||
| 137 | .ready_msg = check_centers_msg, | ||
| 138 | }; | ||
| 139 | |||
| 140 | /* CO steps **************************/ | ||
| 141 | /* TODO: coany_HTM (generic), cofb_HTM, corl_HTM, coud_HTM */ | ||
| 142 | /* TODO: coany_URF (generic), cofb_URF, corl_URF, coud_URF */ | ||
| 143 | |||
| 144 | /* Misc corner steps *****************/ | ||
| 145 | /* TODO: cornershtr_HTM, cornershtr_URF, corners_HTM, corners_URF */ | ||
| 146 | /* TODO (new): corners_drud */ | ||
| 147 | |||
| 148 | /* DR steps **************************/ | ||
| 149 | /* TODO: dr_eo (generic) */ | ||
| 150 | /* TODO: dr_eofb (generic), dr_eorl (generic), dr_eoud (generic) */ | ||
| 151 | /* TODO: drud_eofb, drrl_eofb, drud_eorl, drfb_eorl, drrl_eoud, drfb_eoud */ | ||
| 152 | |||
| 153 | StepAlt | ||
| 154 | sa_drud_HTM = { | ||
| 155 | .ready = check_centers, | ||
| 156 | .final = false, | ||
| 157 | .moveset = &moveset_HTM, | ||
| 158 | .n_coord = 1, | ||
| 159 | .coord = {&coord_drud_sym16}, | ||
| 160 | .coord_trans = {uf}, | ||
| 161 | .compact_pd = {false}, /* TODO: maybe compactify */ | ||
| 162 | .n_dbtrick = 0, | ||
| 163 | .is_valid = validate_singlecw_ending, | ||
| 164 | }; | ||
| 165 | Step | ||
| 166 | drany_HTM = { | ||
| 167 | .shortname = "dr", | ||
| 168 | .name = "DR on any axis", | ||
| 169 | .alt = {&sa_drud_HTM, &sa_drud_HTM, &sa_drud_HTM, NULL}, | ||
| 170 | .t = {uf, rf, fd}, | ||
| 171 | .ready_msg = check_centers_msg, | ||
| 172 | }; | ||
| 173 | Step | ||
| 174 | drud_HTM = { | ||
| 175 | .shortname = "drud", | ||
| 176 | .name = "DR on U/D", | ||
| 177 | .alt = {&sa_drud_HTM, NULL}, | ||
| 178 | .t = {uf}, | ||
| 179 | .ready_msg = check_centers_msg, | ||
| 180 | }; | ||
| 181 | Step | ||
| 182 | drrl_HTM = { | ||
| 183 | .shortname = "drrl", | ||
| 184 | .name = "DR on R/L", | ||
| 185 | .alt = {&sa_drud_HTM, NULL}, | ||
| 186 | .t = {rf}, | ||
| 187 | .ready_msg = check_centers_msg, | ||
| 188 | }; | ||
| 189 | Step | ||
| 190 | drfb_HTM = { | ||
| 191 | .shortname = "drfb", | ||
| 192 | .name = "DR on F/B", | ||
| 193 | .alt = {&sa_drud_HTM, NULL}, | ||
| 194 | .t = {fd}, | ||
| 195 | .ready_msg = check_centers_msg, | ||
| 196 | }; | ||
| 197 | |||
| 198 | /* DR finish steps */ | ||
| 199 | StepAlt | ||
| 200 | sa_drfin_drud = { | ||
| 201 | .ready = check_drud, | ||
| 202 | .final = true, | ||
| 203 | .moveset = &moveset_drud, | ||
| 204 | .n_coord = 1, | ||
| 205 | .coord = {&coord_drudfin_noE_sym16}, /* TODO: maybe no noE */ | ||
| 206 | .coord_trans = {uf}, | ||
| 207 | .compact_pd = {false}, /* TODO: maybe compactify */ | ||
| 208 | .n_dbtrick = 0, | ||
| 209 | .is_valid = NULL, | ||
| 210 | }; | ||
| 211 | Step | ||
| 212 | dranyfin_DR = { | ||
| 213 | .shortname = "drfin", | ||
| 214 | .name = "DR finish on any axis without breaking DR", | ||
| 215 | .alt = {&sa_drfin_drud, &sa_drfin_drud, &sa_drfin_drud, NULL}, | ||
| 216 | .t = {uf, rf, fd}, | ||
| 217 | .ready_msg = check_dr_msg, | ||
| 218 | }; | ||
| 219 | Step | ||
| 220 | drudfin_drud = { | ||
| 221 | .shortname = "drudfin", | ||
| 222 | .name = "DR finis on U/D without breaking DR", | ||
| 223 | .alt = {&sa_drfin_drud, NULL}, | ||
| 224 | .t = {uf}, | ||
| 225 | .ready_msg = check_dr_msg, | ||
| 226 | }; | ||
| 227 | Step | ||
| 228 | drrlfin_drrl = { | ||
| 229 | .shortname = "drrlfin", | ||
| 230 | .name = "DR finish on R/L without breaking DR", | ||
| 231 | .alt = {&sa_drfin_drud, NULL}, | ||
| 232 | .t = {rf}, | ||
| 233 | .ready_msg = check_dr_msg, | ||
| 234 | }; | ||
| 235 | Step | ||
| 236 | drfbfin_drfb = { | ||
| 237 | .shortname = "drfbfin", | ||
| 238 | .name = "DR finish on F/B without breaking DR", | ||
| 239 | .alt = {&sa_drfin_drud, NULL}, | ||
| 240 | .t = {fd}, | ||
| 241 | .ready_msg = check_dr_msg, | ||
| 242 | }; | ||
| 243 | |||
| 244 | /* HTR from DR */ | ||
| 245 | /* TODO: htr_any (generic), htr_drud, htr_drrl, htr_drfb */ | ||
| 246 | |||
| 247 | /* HTR finish */ | ||
| 248 | /* TODO: htrfin_htr */ | ||
| 249 | |||
| 250 | Step *steps[] = { | ||
| 251 | &optimal_HTM, /* first is default */ | ||
| 252 | |||
| 253 | &eoany_HTM, &eofb_HTM, &eorl_HTM, &eoud_HTM, | ||
| 254 | &drany_HTM, &drud_HTM, &drrl_HTM, &drfb_HTM, | ||
| 255 | &dranyfin_DR, &drudfin_drud, &drrlfin_drrl, &drfbfin_drfb, | ||
| 256 | |||
| 257 | /* TODO: | ||
| 258 | &optimal_light_HTM, | ||
| 259 | |||
| 260 | &eofin_eo, &eofbfin_eofb, &eorlfin_eorl, &eoudfin_eoud, | ||
| 261 | &coany_HTM, &coud_HTM, &corl_HTM, &cofb_HTM, | ||
| 262 | &coany_URF, &coud_URF, &corl_URF, &cofb_URF, | ||
| 263 | &dr_eo, &dr_eofb, &dr_eorl, &dr_eoud, | ||
| 264 | &drud_eofb, &drrl_eofb, | ||
| 265 | &drud_eorl, &drfb_eorl, | ||
| 266 | &drfb_eoud, &drrl_eoud, | ||
| 267 | &htr_any, &htr_drud, &htr_drrl, &htr_drfb, | ||
| 268 | &htrfin_htr, | ||
| 269 | &cornershtr_HTM, &cornershtr_URF, &corners_HTM, &corners_URF, | ||
| 270 | NULL | ||
| 271 | */ | ||
| 272 | |||
| 273 | }; | ||
| 274 | |||
| 275 | #endif | ||
| 16 | 276 | ||
| 17 | #endif | 277 | #endif |
diff --git a/src/symcoord.c b/src/symcoord.c deleted file mode 100644 index 20d7c28..0000000 --- a/src/symcoord.c +++ /dev/null | |||
| @@ -1,687 +0,0 @@ | |||
| 1 | #include "symcoord.h" | ||
| 2 | |||
| 3 | /* These constants have been computed generating the respective SymData */ | ||
| 4 | #define CLASSES_CP_16 2768 | ||
| 5 | #define CLASSES_EOFBEPOS_16 64430 | ||
| 6 | |||
| 7 | static uint64_t index_cp_sym16(Cube cube); | ||
| 8 | static uint64_t index_eofbepos_sym16(Cube cube); | ||
| 9 | static uint64_t index_drud_sym16(Cube cube); | ||
| 10 | static uint64_t index_drudfin_noE_sym16(Cube cube); | ||
| 11 | static uint64_t index_nxopt31(Cube cube); | ||
| 12 | |||
| 13 | static uint64_t move_cp_sym16(Move m, uint64_t ind); | ||
| 14 | static uint64_t move_eofbepos_sym16(Move m, uint64_t ind); | ||
| 15 | static uint64_t move_drud_sym16(Move m, uint64_t ind); | ||
| 16 | static uint64_t move_drudfin_noE_sym16(Move m, uint64_t ind); | ||
| 17 | static uint64_t move_nxopt31(Move m, uint64_t ind); | ||
| 18 | |||
| 19 | static int tfind_from_mask(uint64_t mask, Trans *ret); | ||
| 20 | static int tfind_drud_sym16(uint64_t ind, Trans *ret); | ||
| 21 | static int tfind_drudfin_noE_sym16(uint64_t ind, Trans *ret); | ||
| 22 | static int tfind_nxopt31(uint64_t ind, Trans *ret); | ||
| 23 | |||
| 24 | static uint64_t transform_cp(Trans t, uint64_t ind); | ||
| 25 | static uint64_t transform_eofbepos(Trans t, uint64_t ind); | ||
| 26 | static uint64_t transform_drud_sym16(Trans t, uint64_t ind); | ||
| 27 | static uint64_t transform_drudfin_noE_sym16(Trans t, uint64_t ind); | ||
| 28 | static uint64_t transform_nxopt31(Trans t, uint64_t ind); | ||
| 29 | |||
| 30 | static void gensym(SymData *sd); | ||
| 31 | static void init_symc_moves(); | ||
| 32 | static void init_symc_trans(); | ||
| 33 | static bool read_symdata_file(SymData *sd); | ||
| 34 | static bool read_symc_moves_file(); | ||
| 35 | static bool read_symc_trans_file(); | ||
| 36 | static bool write_symdata_file(SymData *sd); | ||
| 37 | static bool write_symc_moves_file(); | ||
| 38 | static bool write_symc_trans_file(); | ||
| 39 | |||
| 40 | /* Some tables ***************************************************************/ | ||
| 41 | |||
| 42 | static uint64_t move_cp_16[NMOVES][CLASSES_CP_16]; | ||
| 43 | static uint64_t move_eofbepos_16[NMOVES][CLASSES_EOFBEPOS_16]; | ||
| 44 | |||
| 45 | static int trans_eofbepos[NTRANS][POW2TO11*BINOM12ON4]; | ||
| 46 | static int trans_epud[NTRANS][FACTORIAL8]; | ||
| 47 | static int trans_cpud_separate[NTRANS][BINOM8ON4]; | ||
| 48 | |||
| 49 | static Trans ttrep_move_cp_16[NMOVES][CLASSES_CP_16]; | ||
| 50 | static Trans ttrep_move_eofbepos_16[NMOVES][CLASSES_EOFBEPOS_16]; | ||
| 51 | |||
| 52 | |||
| 53 | /* Transformation groups and symmetry data ***********************************/ | ||
| 54 | |||
| 55 | static Trans | ||
| 56 | trans_group_udfix[16] = { | ||
| 57 | uf, ur, ub, ul, | ||
| 58 | df, dr, db, dl, | ||
| 59 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 60 | df_mirror, dr_mirror, db_mirror, dl_mirror, | ||
| 61 | }; | ||
| 62 | |||
| 63 | static SymData | ||
| 64 | sd_cp_16 = { | ||
| 65 | .filename = "sd_cp_16_new", | ||
| 66 | .coord = &coord_cp, | ||
| 67 | .sym_coord = &coord_cp_sym16, | ||
| 68 | .ntrans = 16, | ||
| 69 | .trans = trans_group_udfix, | ||
| 70 | .transform = transform_cp, | ||
| 71 | }; | ||
| 72 | |||
| 73 | static SymData | ||
| 74 | sd_eofbepos_16 = { | ||
| 75 | .filename = "sd_eofbepos_16_new", | ||
| 76 | .coord = &coord_eofbepos, | ||
| 77 | .sym_coord = &coord_eofbepos_sym16, | ||
| 78 | .ntrans = 16, | ||
| 79 | .trans = trans_group_udfix, | ||
| 80 | .transform = transform_eofbepos, | ||
| 81 | }; | ||
| 82 | |||
| 83 | SymData * all_sd[] = { | ||
| 84 | &sd_cp_16, | ||
| 85 | &sd_eofbepos_16, | ||
| 86 | NULL | ||
| 87 | }; | ||
| 88 | |||
| 89 | |||
| 90 | /* Coordinates and their implementation **************************************/ | ||
| 91 | |||
| 92 | Coordinate | ||
| 93 | coord_eofbepos_sym16 = { | ||
| 94 | .index = index_eofbepos_sym16, | ||
| 95 | .move = move_eofbepos_sym16, | ||
| 96 | }; | ||
| 97 | |||
| 98 | Coordinate | ||
| 99 | coord_cp_sym16 = { | ||
| 100 | .index = index_cp_sym16, | ||
| 101 | .move = move_cp_sym16, | ||
| 102 | }; | ||
| 103 | |||
| 104 | Coordinate | ||
| 105 | coord_drud_sym16 = { | ||
| 106 | .index = index_drud_sym16, | ||
| 107 | .move = move_drud_sym16, | ||
| 108 | .max = POW3TO7 * CLASSES_EOFBEPOS_16, | ||
| 109 | .base = &coord_eofbepos_sym16, | ||
| 110 | .transform = transform_drud_sym16, | ||
| 111 | .tfind = tfind_drud_sym16, | ||
| 112 | }; | ||
| 113 | |||
| 114 | Coordinate | ||
| 115 | coord_drudfin_noE_sym16 = { | ||
| 116 | .index = index_drudfin_noE_sym16, | ||
| 117 | .move = move_drudfin_noE_sym16, | ||
| 118 | .max = FACTORIAL8 * CLASSES_CP_16, | ||
| 119 | .base = &coord_cp_sym16, | ||
| 120 | .transform = transform_drudfin_noE_sym16, | ||
| 121 | .tfind = tfind_drudfin_noE_sym16, | ||
| 122 | }; | ||
| 123 | |||
| 124 | Coordinate | ||
| 125 | coord_nxopt31 = { | ||
| 126 | .index = index_nxopt31, | ||
| 127 | .move = move_nxopt31, | ||
| 128 | .max = POW3TO7 * BINOM8ON4 * CLASSES_EOFBEPOS_16, | ||
| 129 | .base = &coord_eofbepos_sym16, | ||
| 130 | .transform = transform_nxopt31, | ||
| 131 | .tfind = tfind_nxopt31, | ||
| 132 | }; | ||
| 133 | |||
| 134 | /* Functions *****************************************************************/ | ||
| 135 | |||
| 136 | static uint64_t | ||
| 137 | index_cp_sym16(Cube cube) | ||
| 138 | { | ||
| 139 | return sd_cp_16.class[coord_cp.index(cube)]; | ||
| 140 | } | ||
| 141 | |||
| 142 | static uint64_t | ||
| 143 | index_drud_sym16(Cube cube) | ||
| 144 | { | ||
| 145 | Trans t; | ||
| 146 | |||
| 147 | t = sd_eofbepos_16.transtorep[coord_eofbepos.index(cube)]; | ||
| 148 | |||
| 149 | return index_eofbepos_sym16(cube) * POW3TO7 + co_ttable[t][cube.coud]; | ||
| 150 | } | ||
| 151 | |||
| 152 | static uint64_t | ||
| 153 | index_drudfin_noE_sym16(Cube cube) | ||
| 154 | { | ||
| 155 | Trans t; | ||
| 156 | Cube c; | ||
| 157 | |||
| 158 | t = sd_cp_16.transtorep[coord_cp.index(cube)]; | ||
| 159 | c = apply_trans(t, cube); | ||
| 160 | |||
| 161 | /* TODO: add transform to coord_epud to make this faster */ | ||
| 162 | return index_cp_sym16(c) * FACTORIAL8 + coord_epud.index(c); | ||
| 163 | } | ||
| 164 | |||
| 165 | static uint64_t | ||
| 166 | index_eofbepos_sym16(Cube cube) | ||
| 167 | { | ||
| 168 | return sd_eofbepos_16.class[coord_eofbepos.index(cube)]; | ||
| 169 | } | ||
| 170 | |||
| 171 | static uint64_t | ||
| 172 | index_nxopt31(Cube cube) | ||
| 173 | { | ||
| 174 | Trans t; | ||
| 175 | uint64_t a; | ||
| 176 | int coud, cp; | ||
| 177 | |||
| 178 | t = sd_eofbepos_16.transtorep[coord_eofbepos.index(cube)]; | ||
| 179 | coud = co_ttable[t][cube.coud]; | ||
| 180 | cp = cp_ttable[t][cube.cp]; | ||
| 181 | a = (index_eofbepos_sym16(cube)*POW3TO7) + coud; | ||
| 182 | |||
| 183 | return a * BINOM8ON4 + coord_cpud_separate.index((Cube){.cp = cp}); | ||
| 184 | } | ||
| 185 | |||
| 186 | static uint64_t | ||
| 187 | move_cp_sym16(Move m, uint64_t ind) | ||
| 188 | { | ||
| 189 | return move_cp_16[m][ind]; | ||
| 190 | } | ||
| 191 | |||
| 192 | static uint64_t | ||
| 193 | move_eofbepos_sym16(Move m, uint64_t ind) | ||
| 194 | { | ||
| 195 | return move_eofbepos_16[m][ind]; | ||
| 196 | } | ||
| 197 | |||
| 198 | static uint64_t | ||
| 199 | move_drud_sym16(Move m, uint64_t ind) | ||
| 200 | { | ||
| 201 | uint64_t coud, eofbepos; | ||
| 202 | Trans ttr; | ||
| 203 | |||
| 204 | eofbepos = move_eofbepos_16[m][ind / POW3TO7]; | ||
| 205 | ttr = ttrep_move_eofbepos_16[m][ind / POW3TO7]; | ||
| 206 | coud = coud_mtable[m][ind % POW3TO7]; | ||
| 207 | coud = co_ttable[ttr][coud]; /* Source is always coud */ | ||
| 208 | |||
| 209 | return eofbepos * POW3TO7 + coud; | ||
| 210 | } | ||
| 211 | |||
| 212 | static uint64_t | ||
| 213 | move_drudfin_noE_sym16(Move m, uint64_t ind) | ||
| 214 | { | ||
| 215 | uint64_t cp, epud; | ||
| 216 | Trans ttr; | ||
| 217 | |||
| 218 | cp = move_cp_16[m][ind / FACTORIAL8]; | ||
| 219 | ttr = ttrep_move_cp_16[m][ind / FACTORIAL8]; | ||
| 220 | epud = coord_epud.move(m, ind % FACTORIAL8); | ||
| 221 | epud = trans_epud[ttr][epud]; | ||
| 222 | |||
| 223 | return cp * FACTORIAL8 + epud; | ||
| 224 | } | ||
| 225 | |||
| 226 | static uint64_t | ||
| 227 | move_nxopt31(Move m, uint64_t ind) | ||
| 228 | { | ||
| 229 | uint64_t eofbepos, cpsep, coud; | ||
| 230 | Trans ttr; | ||
| 231 | |||
| 232 | eofbepos = ind / (POW3TO7 * BINOM8ON4); | ||
| 233 | coud = (ind / BINOM8ON4) % POW3TO7; | ||
| 234 | cpsep = ind % BINOM8ON4; | ||
| 235 | |||
| 236 | ttr = ttrep_move_eofbepos_16[m][eofbepos]; | ||
| 237 | eofbepos = move_eofbepos_16[m][eofbepos]; | ||
| 238 | coud = coud_mtable[m][coud]; | ||
| 239 | coud = co_ttable[ttr][coud]; /* Source is always coud */ | ||
| 240 | cpsep = coord_cpud_separate.move(m, cpsep); | ||
| 241 | cpsep = trans_cpud_separate[ttr][cpsep]; | ||
| 242 | |||
| 243 | return (eofbepos * POW3TO7 + coud) * BINOM8ON4 + cpsep; | ||
| 244 | } | ||
| 245 | |||
| 246 | static uint64_t | ||
| 247 | transform_cp(Trans t, uint64_t ind) | ||
| 248 | { | ||
| 249 | return cp_ttable[t][ind]; | ||
| 250 | } | ||
| 251 | |||
| 252 | static uint64_t | ||
| 253 | transform_eofbepos(Trans t, uint64_t ind) | ||
| 254 | { | ||
| 255 | return trans_eofbepos[t][ind]; | ||
| 256 | } | ||
| 257 | |||
| 258 | static uint64_t | ||
| 259 | transform_drud_sym16(Trans t, uint64_t ind) | ||
| 260 | { | ||
| 261 | uint64_t coud, eofbepos; | ||
| 262 | |||
| 263 | eofbepos = ind / POW3TO7; /* Assum trans fixes eofbepos */ | ||
| 264 | coud = co_ttable[t][ind % POW3TO7]; /* Source is always coud */ | ||
| 265 | |||
| 266 | return eofbepos * POW3TO7 + coud; | ||
| 267 | } | ||
| 268 | |||
| 269 | static uint64_t | ||
| 270 | transform_drudfin_noE_sym16(Trans t, uint64_t ind) | ||
| 271 | { | ||
| 272 | uint64_t cp, epud; | ||
| 273 | |||
| 274 | cp = ind / FACTORIAL8; /* Assume trans fixes cp */ | ||
| 275 | epud = trans_epud[t][ind % FACTORIAL8]; | ||
| 276 | |||
| 277 | return cp * FACTORIAL8 + epud; | ||
| 278 | } | ||
| 279 | |||
| 280 | static uint64_t | ||
| 281 | transform_nxopt31(Trans t, uint64_t ind) | ||
| 282 | { | ||
| 283 | uint64_t eofbepos, cpsep, coud; | ||
| 284 | |||
| 285 | eofbepos = ind / (POW3TO7 * BINOM8ON4); | ||
| 286 | coud = (ind / BINOM8ON4) % POW3TO7; | ||
| 287 | cpsep = ind % BINOM8ON4; | ||
| 288 | |||
| 289 | coud = co_ttable[t][coud]; /* Source is always coud */ | ||
| 290 | cpsep = trans_cpud_separate[t][cpsep]; | ||
| 291 | |||
| 292 | return (eofbepos * POW3TO7 + coud) * BINOM8ON4 + cpsep; | ||
| 293 | } | ||
| 294 | |||
| 295 | static int | ||
| 296 | tfind_from_mask(uint64_t mask, Trans *ret) | ||
| 297 | { | ||
| 298 | Trans t; | ||
| 299 | int i = 0; | ||
| 300 | |||
| 301 | for (t = uf; t < NTRANS; t++) | ||
| 302 | if (((uint64_t)1 << t) & mask) | ||
| 303 | ret[i++] = t; | ||
| 304 | |||
| 305 | return i; | ||
| 306 | } | ||
| 307 | |||
| 308 | static int | ||
| 309 | tfind_drud_sym16(uint64_t ind, Trans *ret) | ||
| 310 | { | ||
| 311 | uint64_t mask = sd_eofbepos_16.selfsim[ind / POW3TO7]; | ||
| 312 | |||
| 313 | return tfind_from_mask(mask, ret); | ||
| 314 | } | ||
| 315 | |||
| 316 | static int | ||
| 317 | tfind_drudfin_noE_sym16(uint64_t ind, Trans *ret) | ||
| 318 | { | ||
| 319 | uint64_t mask = sd_cp_16.selfsim[ind / FACTORIAL8]; | ||
| 320 | |||
| 321 | return tfind_from_mask(mask, ret); | ||
| 322 | } | ||
| 323 | |||
| 324 | static int | ||
| 325 | tfind_nxopt31(uint64_t ind, Trans *ret) | ||
| 326 | { | ||
| 327 | uint64_t mask = sd_eofbepos_16.selfsim[ind / (POW3TO7 * BINOM8ON4)]; | ||
| 328 | |||
| 329 | return tfind_from_mask(mask, ret); | ||
| 330 | } | ||
| 331 | |||
| 332 | /* Other functions ***********************************************************/ | ||
| 333 | |||
| 334 | void | ||
| 335 | free_sd(SymData *sd) | ||
| 336 | { | ||
| 337 | if (sd->generated) { | ||
| 338 | free(sd->class); | ||
| 339 | free(sd->unsym); | ||
| 340 | free(sd->transtorep); | ||
| 341 | } | ||
| 342 | |||
| 343 | sd->generated = false; | ||
| 344 | } | ||
| 345 | |||
| 346 | static void | ||
| 347 | gensym(SymData *sd) | ||
| 348 | { | ||
| 349 | uint64_t i, in, nreps = 0; | ||
| 350 | Trans t; | ||
| 351 | int j; | ||
| 352 | |||
| 353 | if (sd->generated) | ||
| 354 | return; | ||
| 355 | |||
| 356 | sd->class = malloc(sd->coord->max * sizeof(uint64_t)); | ||
| 357 | sd->unsym = malloc(sd->coord->max * sizeof(uint64_t)); | ||
| 358 | sd->transtorep = malloc(sd->coord->max * sizeof(Trans)); | ||
| 359 | sd->selfsim = malloc(sd->coord->max * sizeof(uint64_t)); | ||
| 360 | |||
| 361 | if (read_symdata_file(sd)) { | ||
| 362 | sd->generated = true; | ||
| 363 | return; | ||
| 364 | } | ||
| 365 | |||
| 366 | fprintf(stderr, "Cannot load %s, generating it\n", sd->filename); | ||
| 367 | |||
| 368 | for (i = 0; i < sd->coord->max; i++) | ||
| 369 | sd->class[i] = sd->coord->max + 1; | ||
| 370 | |||
| 371 | for (i = 0; i < sd->coord->max; i++) { | ||
| 372 | if (sd->class[i] == sd->coord->max + 1) { | ||
| 373 | sd->unsym[nreps] = i; | ||
| 374 | sd->transtorep[i] = uf; | ||
| 375 | sd->selfsim[nreps] = (uint64_t)0; | ||
| 376 | for (j = 0; j < sd->ntrans; j++) { | ||
| 377 | t = sd->trans[j]; | ||
| 378 | in = sd->transform(t, i); | ||
| 379 | sd->class[in] = nreps; | ||
| 380 | if (in == i) | ||
| 381 | sd->selfsim[nreps] |= | ||
| 382 | ((uint64_t)1 << t); | ||
| 383 | else | ||
| 384 | sd->transtorep[in] = inverse_trans(t); | ||
| 385 | } | ||
| 386 | nreps++; | ||
| 387 | } | ||
| 388 | } | ||
| 389 | |||
| 390 | sd->sym_coord->max = nreps; | ||
| 391 | sd->unsym = realloc(sd->unsym, nreps * sizeof(uint64_t)); | ||
| 392 | sd->selfsim = realloc(sd->selfsim, nreps * sizeof(uint64_t)); | ||
| 393 | sd->generated = true; | ||
| 394 | |||
| 395 | fprintf(stderr, "Found %" PRIu64 " classes\n", nreps); | ||
| 396 | |||
| 397 | if (!write_symdata_file(sd)) | ||
| 398 | fprintf(stderr, "Error writing SymData file\n"); | ||
| 399 | |||
| 400 | return; | ||
| 401 | } | ||
| 402 | |||
| 403 | static bool | ||
| 404 | read_symdata_file(SymData *sd) | ||
| 405 | { | ||
| 406 | init_env(); | ||
| 407 | |||
| 408 | FILE *f; | ||
| 409 | char fname[strlen(tabledir)+100]; | ||
| 410 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 411 | bool r = true; | ||
| 412 | |||
| 413 | strcpy(fname, tabledir); | ||
| 414 | strcat(fname, "/"); | ||
| 415 | strcat(fname, sd->filename); | ||
| 416 | |||
| 417 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 418 | return false; | ||
| 419 | |||
| 420 | r = r && fread(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 421 | r = r && fread(sd->unsym, sizeof(uint64_t), *sn, f) == *sn; | ||
| 422 | r = r && fread(sd->selfsim, sizeof(uint64_t), *sn, f) == *sn; | ||
| 423 | r = r && fread(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 424 | r = r && fread(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 425 | |||
| 426 | fclose(f); | ||
| 427 | return r; | ||
| 428 | } | ||
| 429 | |||
| 430 | static bool | ||
| 431 | read_symc_moves_file() | ||
| 432 | { | ||
| 433 | init_env(); | ||
| 434 | |||
| 435 | Move m; | ||
| 436 | bool r = true; | ||
| 437 | FILE *f; | ||
| 438 | char fname[strlen(tabledir)+100]; | ||
| 439 | |||
| 440 | strcpy(fname, tabledir); | ||
| 441 | strcat(fname, "/symc_moves"); | ||
| 442 | |||
| 443 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 444 | return false; | ||
| 445 | |||
| 446 | for (m = 0; m < NMOVES; m++) { | ||
| 447 | r = r && fread(move_cp_16[m], sizeof(uint64_t), | ||
| 448 | CLASSES_CP_16, f) == CLASSES_CP_16; | ||
| 449 | r = r && fread(move_eofbepos_16[m], sizeof(uint64_t), | ||
| 450 | CLASSES_EOFBEPOS_16, f) == CLASSES_EOFBEPOS_16; | ||
| 451 | |||
| 452 | r = r && fread(ttrep_move_cp_16[m], sizeof(Trans), | ||
| 453 | CLASSES_CP_16, f) == CLASSES_CP_16; | ||
| 454 | r = r && fread(ttrep_move_eofbepos_16[m], sizeof(Trans), | ||
| 455 | CLASSES_EOFBEPOS_16, f) == CLASSES_EOFBEPOS_16; | ||
| 456 | } | ||
| 457 | |||
| 458 | fclose(f); | ||
| 459 | return r; | ||
| 460 | } | ||
| 461 | |||
| 462 | static bool | ||
| 463 | read_symc_trans_file() | ||
| 464 | { | ||
| 465 | init_env(); | ||
| 466 | |||
| 467 | Trans t; | ||
| 468 | bool r = true; | ||
| 469 | FILE *f; | ||
| 470 | char fname[strlen(tabledir)+100]; | ||
| 471 | |||
| 472 | strcpy(fname, tabledir); | ||
| 473 | strcat(fname, "/symc_trans"); | ||
| 474 | |||
| 475 | if ((f = fopen(fname, "rb")) == NULL) | ||
| 476 | return false; | ||
| 477 | |||
| 478 | for (t = 0; t < NTRANS; t++) { | ||
| 479 | r = r && fread(trans_eofbepos[t], sizeof(int), | ||
| 480 | POW2TO11*BINOM12ON4, f) == POW2TO11*BINOM12ON4; | ||
| 481 | r = r && fread(trans_epud[t], sizeof(int), | ||
| 482 | FACTORIAL8, f) == FACTORIAL8; | ||
| 483 | r = r && fread(trans_cpud_separate[t], sizeof(int), | ||
| 484 | BINOM8ON4, f) == BINOM8ON4; | ||
| 485 | } | ||
| 486 | |||
| 487 | fclose(f); | ||
| 488 | return r; | ||
| 489 | } | ||
| 490 | |||
| 491 | static bool | ||
| 492 | write_symdata_file(SymData *sd) | ||
| 493 | { | ||
| 494 | init_env(); | ||
| 495 | |||
| 496 | FILE *f; | ||
| 497 | char fname[strlen(tabledir)+100]; | ||
| 498 | uint64_t n = sd->coord->max, *sn = &sd->sym_coord->max; | ||
| 499 | bool r = true; | ||
| 500 | |||
| 501 | strcpy(fname, tabledir); | ||
| 502 | strcat(fname, "/"); | ||
| 503 | strcat(fname, sd->filename); | ||
| 504 | |||
| 505 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 506 | return false; | ||
| 507 | |||
| 508 | r = r && fwrite(&sd->sym_coord->max, sizeof(uint64_t), 1, f) == 1; | ||
| 509 | r = r && fwrite(sd->unsym, sizeof(uint64_t), *sn, f) == *sn; | ||
| 510 | r = r && fwrite(sd->selfsim, sizeof(uint64_t), *sn, f) == *sn; | ||
| 511 | r = r && fwrite(sd->class, sizeof(uint64_t), n, f) == n; | ||
| 512 | r = r && fwrite(sd->transtorep, sizeof(Trans), n, f) == n; | ||
| 513 | |||
| 514 | fclose(f); | ||
| 515 | return r; | ||
| 516 | } | ||
| 517 | |||
| 518 | static bool | ||
| 519 | write_symc_moves_file() | ||
| 520 | { | ||
| 521 | init_env(); | ||
| 522 | |||
| 523 | Move m; | ||
| 524 | bool r = true; | ||
| 525 | FILE *f; | ||
| 526 | char fname[strlen(tabledir)+100]; | ||
| 527 | |||
| 528 | strcpy(fname, tabledir); | ||
| 529 | strcat(fname, "/symc_moves"); | ||
| 530 | |||
| 531 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 532 | return false; | ||
| 533 | |||
| 534 | for (m = 0; m < NMOVES; m++) { | ||
| 535 | r = r && fwrite(move_cp_16[m], sizeof(uint64_t), | ||
| 536 | CLASSES_CP_16, f) == CLASSES_CP_16; | ||
| 537 | r = r && fwrite(move_eofbepos_16[m], sizeof(uint64_t), | ||
| 538 | CLASSES_EOFBEPOS_16, f) == CLASSES_EOFBEPOS_16; | ||
| 539 | |||
| 540 | r = r && fwrite(ttrep_move_cp_16[m], sizeof(Trans), | ||
| 541 | CLASSES_CP_16, f) == CLASSES_CP_16; | ||
| 542 | r = r && fwrite(ttrep_move_eofbepos_16[m], sizeof(Trans), | ||
| 543 | CLASSES_EOFBEPOS_16, f) == CLASSES_EOFBEPOS_16; | ||
| 544 | } | ||
| 545 | |||
| 546 | fclose(f); | ||
| 547 | return r; | ||
| 548 | } | ||
| 549 | |||
| 550 | static bool | ||
| 551 | write_symc_trans_file() | ||
| 552 | { | ||
| 553 | init_env(); | ||
| 554 | |||
| 555 | Trans t; | ||
| 556 | bool r = true; | ||
| 557 | FILE *f; | ||
| 558 | char fname[strlen(tabledir)+100]; | ||
| 559 | |||
| 560 | strcpy(fname, tabledir); | ||
| 561 | strcat(fname, "/symc_trans"); | ||
| 562 | |||
| 563 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 564 | return false; | ||
| 565 | |||
| 566 | for (t = 0; t < NTRANS; t++) { | ||
| 567 | r = r && fwrite(trans_eofbepos[t], sizeof(int), | ||
| 568 | POW2TO11*BINOM12ON4, f) == POW2TO11*BINOM12ON4; | ||
| 569 | r = r && fwrite(trans_epud[t], sizeof(int), | ||
| 570 | FACTORIAL8, f) == FACTORIAL8; | ||
| 571 | r = r && fwrite(trans_cpud_separate[t], sizeof(int), | ||
| 572 | BINOM8ON4, f) == BINOM8ON4; | ||
| 573 | } | ||
| 574 | |||
| 575 | fclose(f); | ||
| 576 | return r; | ||
| 577 | } | ||
| 578 | |||
| 579 | static void | ||
| 580 | init_symc_moves() | ||
| 581 | { | ||
| 582 | uint64_t i, ii, coo; | ||
| 583 | Move j; | ||
| 584 | |||
| 585 | if (read_symc_moves_file()) | ||
| 586 | return; | ||
| 587 | |||
| 588 | for (i = 0; i < CLASSES_CP_16; i++) { | ||
| 589 | ii = sd_cp_16.unsym[i]; | ||
| 590 | for (j = 0; j < NMOVES; j++) { | ||
| 591 | coo = sd_cp_16.coord->move(j, ii); | ||
| 592 | move_cp_16[j][i] = sd_cp_16.class[coo]; | ||
| 593 | ttrep_move_cp_16[j][i] = sd_cp_16.transtorep[coo]; | ||
| 594 | } | ||
| 595 | } | ||
| 596 | |||
| 597 | for (i = 0; i < CLASSES_EOFBEPOS_16; i++) { | ||
| 598 | ii = sd_eofbepos_16.unsym[i]; | ||
| 599 | for (j = 0; j < NMOVES; j++) { | ||
| 600 | coo = sd_eofbepos_16.coord->move(j, ii); | ||
| 601 | move_eofbepos_16[j][i] = sd_eofbepos_16.class[coo]; | ||
| 602 | ttrep_move_eofbepos_16[j][i] = | ||
| 603 | sd_eofbepos_16.transtorep[coo]; | ||
| 604 | } | ||
| 605 | } | ||
| 606 | |||
| 607 | if (!write_symc_moves_file()) | ||
| 608 | fprintf(stderr, "Error writing SymMoves file\n"); | ||
| 609 | } | ||
| 610 | |||
| 611 | void | ||
| 612 | init_symc_trans() | ||
| 613 | { | ||
| 614 | uint64_t i; | ||
| 615 | int j, cp; | ||
| 616 | int epe[4] = {FR, FL, BL, BR}; | ||
| 617 | int a[12] = { [8] = 8, [9] = 9, [10] = 10, [11] = 11 }; | ||
| 618 | Cube c; | ||
| 619 | CubeArray *arr, *aux; | ||
| 620 | Trans t; | ||
| 621 | |||
| 622 | if (read_symc_trans_file()) | ||
| 623 | return; | ||
| 624 | |||
| 625 | for (i = 0; i < POW2TO11*BINOM12ON4; i++) { | ||
| 626 | for (j = 0; j < 16; j++) { | ||
| 627 | t = trans_group_udfix[j]; | ||
| 628 | |||
| 629 | arr = new_cubearray((Cube){0}, pf_edges); | ||
| 630 | int_to_sum_zero_array(i % POW2TO11, 2, 12, arr->eofb); | ||
| 631 | epos_to_compatible_ep((i / POW2TO11)*24, arr->ep, epe); | ||
| 632 | fix_eorleoud(arr); | ||
| 633 | c = arrays_to_cube(arr, pf_edges); | ||
| 634 | free_cubearray(arr, pf_edges); | ||
| 635 | |||
| 636 | c = apply_trans(t, c); | ||
| 637 | trans_eofbepos[t][i] = (c.epose/24)*POW2TO11 + c.eofb; | ||
| 638 | } | ||
| 639 | } | ||
| 640 | |||
| 641 | aux = malloc(sizeof(CubeArray)); | ||
| 642 | aux->ep = a; | ||
| 643 | for (i = 0; i < FACTORIAL8; i++) { | ||
| 644 | index_to_perm(i, 8, a); | ||
| 645 | c = arrays_to_cube(aux, pf_ep); | ||
| 646 | for (j = 0; j < 16; j++) { | ||
| 647 | t = trans_group_udfix[j]; | ||
| 648 | arr = new_cubearray(apply_trans(t, c), pf_ep); | ||
| 649 | trans_epud[t][i] = perm_to_index(arr->ep, 8); | ||
| 650 | free_cubearray(arr, pf_ep); | ||
| 651 | } | ||
| 652 | } | ||
| 653 | free(aux); | ||
| 654 | |||
| 655 | for (i = 0; i < BINOM8ON4; i++) { | ||
| 656 | cp = cpud_separate_ant[i]; | ||
| 657 | for (j = 0; j < 16; j++) { | ||
| 658 | t = trans_group_udfix[j]; | ||
| 659 | trans_cpud_separate[t][i] = | ||
| 660 | cpud_separate_ind[cp_ttable[t][cp]]; | ||
| 661 | } | ||
| 662 | } | ||
| 663 | |||
| 664 | if (!write_symc_trans_file()) | ||
| 665 | fprintf(stderr, "Error writing SymTrans file\n"); | ||
| 666 | } | ||
| 667 | |||
| 668 | void | ||
| 669 | init_symcoord() | ||
| 670 | { | ||
| 671 | int i; | ||
| 672 | |||
| 673 | static bool initialized = false; | ||
| 674 | if (initialized) | ||
| 675 | return; | ||
| 676 | initialized = true; | ||
| 677 | |||
| 678 | init_coord(); | ||
| 679 | |||
| 680 | init_symc_trans(); | ||
| 681 | |||
| 682 | for (i = 0; all_sd[i] != NULL; i++) | ||
| 683 | gensym(all_sd[i]); | ||
| 684 | |||
| 685 | init_symc_moves(); | ||
| 686 | } | ||
| 687 | |||
diff --git a/src/symcoord.h b/src/symcoord.h deleted file mode 100644 index 0882bff..0000000 --- a/src/symcoord.h +++ /dev/null | |||
| @@ -1,17 +0,0 @@ | |||
| 1 | #ifndef SYMCOORD_H | ||
| 2 | #define SYMCOORD_H | ||
| 3 | |||
| 4 | #include "coord.h" | ||
| 5 | |||
| 6 | extern Coordinate coord_cp_sym16; | ||
| 7 | extern Coordinate coord_eofbepos_sym16; | ||
| 8 | extern Coordinate coord_drud_sym16; | ||
| 9 | extern Coordinate coord_drudfin_noE_sym16; | ||
| 10 | extern Coordinate coord_nxopt31; | ||
| 11 | |||
| 12 | extern SymData *all_sd[]; | ||
| 13 | |||
| 14 | void free_sd(SymData *sd); | ||
| 15 | void init_symcoord(); | ||
| 16 | |||
| 17 | #endif | ||
diff --git a/src/trans.c b/src/trans.c index e267a17..da2dca3 100644 --- a/src/trans.c +++ b/src/trans.c | |||
| @@ -1,31 +1,23 @@ | |||
| 1 | #define TRANS_C | ||
| 2 | |||
| 1 | #include "trans.h" | 3 | #include "trans.h" |
| 2 | 4 | ||
| 3 | /* Local functions ***********************************************************/ | 5 | /* Local functions ***********************************************************/ |
| 4 | 6 | ||
| 5 | static bool read_ttables_file(); | ||
| 6 | static Cube rotate_via_compose(Trans r, Cube c, PieceFilter f); | ||
| 7 | static bool write_ttables_file(); | ||
| 8 | |||
| 9 | /* Tables and other data *****************************************************/ | 7 | /* Tables and other data *****************************************************/ |
| 10 | 8 | ||
| 11 | static int ep_mirror[12] = { | 9 | static Cube mirror_cube = { |
| 12 | [UF] = UF, [UL] = UR, [UB] = UB, [UR] = UL, | 10 | .ep = { [UF] = UF, [UL] = UR, [UB] = UB, [UR] = UL, |
| 13 | [DF] = DF, [DL] = DR, [DB] = DB, [DR] = DL, | 11 | [DF] = DF, [DL] = DR, [DB] = DB, [DR] = DL, |
| 14 | [FR] = FL, [FL] = FR, [BL] = BR, [BR] = BL | 12 | [FR] = FL, [FL] = FR, [BL] = BR, [BR] = BL }, |
| 15 | }; | 13 | .cp = { [UFR] = UFL, [UFL] = UFR, [UBL] = UBR, [UBR] = UBL, |
| 16 | 14 | [DFR] = DFL, [DFL] = DFR, [DBL] = DBR, [DBR] = DBL }, | |
| 17 | static int cp_mirror[8] = { | 15 | .xp = { [U_center] = U_center, [D_center] = D_center, |
| 18 | [UFR] = UFL, [UFL] = UFR, [UBL] = UBR, [UBR] = UBL, | ||
| 19 | [DFR] = DFL, [DFL] = DFR, [DBL] = DBR, [DBR] = DBL | ||
| 20 | }; | ||
| 21 | |||
| 22 | static int cpos_mirror[6] = { | ||
| 23 | [U_center] = U_center, [D_center] = D_center, | ||
| 24 | [R_center] = L_center, [L_center] = R_center, | 16 | [R_center] = L_center, [L_center] = R_center, |
| 25 | [F_center] = F_center, [B_center] = B_center | 17 | [F_center] = F_center, [B_center] = B_center } |
| 26 | }; | 18 | }; |
| 27 | 19 | ||
| 28 | static char rotation_alg_string[100][NROTATIONS] = { | 20 | static char rotation_alg_string[100][NROTATIONS] = { |
| 29 | [uf] = "", [ur] = "y", [ub] = "y2", [ul] = "y3", | 21 | [uf] = "", [ur] = "y", [ub] = "y2", [ul] = "y3", |
| 30 | [df] = "z2", [dr] = "y z2", [db] = "x2", [dl] = "y3 z2", | 22 | [df] = "z2", [dr] = "y z2", [db] = "x2", [dl] = "y3 z2", |
| 31 | [rf] = "z3", [rd] = "z3 y", [rb] = "z3 y2", [ru] = "z3 y3", | 23 | [rf] = "z3", [rd] = "z3 y", [rb] = "z3 y2", [ru] = "z3 y3", |
| @@ -34,176 +26,39 @@ static char rotation_alg_string[100][NROTATIONS] = { | |||
| 34 | [bu] = "x3", [br] = "x3 y", [bd] = "x3 y2", [bl] = "x3 y3", | 26 | [bu] = "x3", [br] = "x3 y", [bd] = "x3 y2", [bl] = "x3 y3", |
| 35 | }; | 27 | }; |
| 36 | 28 | ||
| 37 | static int epose_source[NTRANS]; /* 0=epose, 1=eposs, 2=eposm */ | 29 | static Alg *rotation_alg_arr[NROTATIONS]; |
| 38 | static int eposs_source[NTRANS]; | 30 | Move moves_ttable[NTRANS][NMOVES]; |
| 39 | static int eposm_source[NTRANS]; | 31 | Trans trans_ttable[NTRANS][NTRANS]; |
| 40 | static int eofb_source[NTRANS]; /* 0=eoud, 1=eorl, 2=eofb */ | 32 | Trans trans_itable[NTRANS]; |
| 41 | static int eorl_source[NTRANS]; | ||
| 42 | static int eoud_source[NTRANS]; | ||
| 43 | static int coud_source[NTRANS]; /* 0=coud, 1=corl, 2=cofb */ | ||
| 44 | static int cofb_source[NTRANS]; | ||
| 45 | static int corl_source[NTRANS]; | ||
| 46 | 33 | ||
| 47 | int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | 34 | /* Public functions **********************************************************/ |
| 48 | int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 49 | int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 50 | int eo_ttable[NTRANS][POW2TO11]; | ||
| 51 | int cp_ttable[NTRANS][FACTORIAL8]; | ||
| 52 | int co_ttable[NTRANS][POW3TO7]; | ||
| 53 | int cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 54 | Move moves_ttable[NTRANS][NMOVES]; | ||
| 55 | |||
| 56 | /* Local functions implementation ********************************************/ | ||
| 57 | 35 | ||
| 58 | static bool | 36 | void |
| 59 | read_ttables_file() | 37 | apply_trans(Trans t, Cube *cube) |
| 60 | { | 38 | { |
| 61 | init_env(); | 39 | Cube aux; |
| 62 | 40 | Alg *inv; | |
| 63 | FILE *f; | 41 | int i; |
| 64 | char fname[strlen(tabledir)+20]; | ||
| 65 | int b = sizeof(int); | ||
| 66 | bool r = true; | ||
| 67 | Move m; | ||
| 68 | |||
| 69 | /* Table sizes, used for reading and writing files */ | ||
| 70 | uint64_t me[11] = { | ||
| 71 | [0] = FACTORIAL12/FACTORIAL8, | ||
| 72 | [1] = FACTORIAL12/FACTORIAL8, | ||
| 73 | [2] = FACTORIAL12/FACTORIAL8, | ||
| 74 | [3] = POW2TO11, | ||
| 75 | [4] = FACTORIAL8, | ||
| 76 | [5] = POW3TO7, | ||
| 77 | [6] = FACTORIAL6, | ||
| 78 | [7] = NMOVES | ||
| 79 | }; | ||
| 80 | |||
| 81 | strcpy(fname, tabledir); | ||
| 82 | strcat(fname, "/"); | ||
| 83 | strcat(fname, "ttables"); | ||
| 84 | 42 | ||
| 85 | if ((f = fopen(fname, "rb")) == NULL) | 43 | inv = inverse_alg(rotation_alg(t % NROTATIONS)); |
| 86 | return false; | 44 | copy_cube(cube, &aux); |
| 45 | make_solved(cube); | ||
| 87 | 46 | ||
| 88 | for (m = 0; m < NTRANS; m++) { | 47 | if (t >= NROTATIONS) |
| 89 | r = r && fread(epose_ttable[m], b, me[0], f) == me[0]; | 48 | compose(&mirror_cube, cube); |
| 90 | r = r && fread(eposs_ttable[m], b, me[1], f) == me[1]; | 49 | apply_alg(inv, cube); |
| 91 | r = r && fread(eposm_ttable[m], b, me[2], f) == me[2]; | 50 | compose(&aux, cube); |
| 92 | r = r && fread(eo_ttable[m], b, me[3], f) == me[3]; | 51 | apply_alg(rotation_alg(t % NROTATIONS), cube); |
| 93 | r = r && fread(cp_ttable[m], b, me[4], f) == me[4]; | 52 | if (t >= NROTATIONS) { |
| 94 | r = r && fread(co_ttable[m], b, me[5], f) == me[5]; | 53 | compose(&mirror_cube, cube); |
| 95 | r = r && fread(cpos_ttable[m], b, me[6], f) == me[6]; | 54 | for (i = 0; i < 8; i++) |
| 96 | r = r && fread(moves_ttable[m], b, me[7], f) == me[7]; | 55 | cube->co[i] = (3 - cube->co[i]) % 3; |
| 97 | } | 56 | } |
| 98 | 57 | ||
| 99 | fclose(f); | ||
| 100 | return r; | ||
| 101 | } | ||
| 102 | |||
| 103 | static Cube | ||
| 104 | rotate_via_compose(Trans r, Cube c, PieceFilter f) | ||
| 105 | { | ||
| 106 | static int zero12[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 107 | static int zero8[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 108 | static CubeArray ma = { | ||
| 109 | .ep = ep_mirror, | ||
| 110 | .eofb = zero12, | ||
| 111 | .eorl = zero12, | ||
| 112 | .eoud = zero12, | ||
| 113 | .cp = cp_mirror, | ||
| 114 | .coud = zero8, | ||
| 115 | .corl = zero8, | ||
| 116 | .cofb = zero8, | ||
| 117 | .cpos = cpos_mirror | ||
| 118 | }; | ||
| 119 | |||
| 120 | Alg *inv = inverse_alg(rotation_alg(r)); | ||
| 121 | Cube ret = {0}; | ||
| 122 | |||
| 123 | if (r >= NROTATIONS) | ||
| 124 | ret = move_via_arrays(&ma, ret, f); | ||
| 125 | ret = apply_alg_generic(inv, ret, f, true); | ||
| 126 | |||
| 127 | ret = compose_filtered(c, ret, f); | ||
| 128 | |||
| 129 | ret = apply_alg_generic(rotation_alg(r), ret, f, true); | ||
| 130 | if (r >= NROTATIONS) | ||
| 131 | ret = move_via_arrays(&ma, ret, f); | ||
| 132 | |||
| 133 | free_alg(inv); | 58 | free_alg(inv); |
| 134 | return ret; | ||
| 135 | } | ||
| 136 | |||
| 137 | static bool | ||
| 138 | write_ttables_file() | ||
| 139 | { | ||
| 140 | init_env(); | ||
| 141 | |||
| 142 | FILE *f; | ||
| 143 | char fname[strlen(tabledir)+20]; | ||
| 144 | bool r = true; | ||
| 145 | int b = sizeof(int); | ||
| 146 | Move m; | ||
| 147 | |||
| 148 | /* Table sizes, used for reading and writing files */ | ||
| 149 | uint64_t me[11] = { | ||
| 150 | [0] = FACTORIAL12/FACTORIAL8, | ||
| 151 | [1] = FACTORIAL12/FACTORIAL8, | ||
| 152 | [2] = FACTORIAL12/FACTORIAL8, | ||
| 153 | [3] = POW2TO11, | ||
| 154 | [4] = FACTORIAL8, | ||
| 155 | [5] = POW3TO7, | ||
| 156 | [6] = FACTORIAL6, | ||
| 157 | [7] = NMOVES | ||
| 158 | }; | ||
| 159 | |||
| 160 | strcpy(fname, tabledir); | ||
| 161 | strcat(fname, "/ttables"); | ||
| 162 | |||
| 163 | if ((f = fopen(fname, "wb")) == NULL) | ||
| 164 | return false; | ||
| 165 | |||
| 166 | for (m = 0; m < NTRANS; m++) { | ||
| 167 | r = r && fwrite(epose_ttable[m], b, me[0], f) == me[0]; | ||
| 168 | r = r && fwrite(eposs_ttable[m], b, me[1], f) == me[1]; | ||
| 169 | r = r && fwrite(eposm_ttable[m], b, me[2], f) == me[2]; | ||
| 170 | r = r && fwrite(eo_ttable[m], b, me[3], f) == me[3]; | ||
| 171 | r = r && fwrite(cp_ttable[m], b, me[4], f) == me[4]; | ||
| 172 | r = r && fwrite(co_ttable[m], b, me[5], f) == me[5]; | ||
| 173 | r = r && fwrite(cpos_ttable[m], b, me[6], f) == me[6]; | ||
| 174 | r = r && fwrite(moves_ttable[m], b, me[7], f) == me[7]; | ||
| 175 | } | ||
| 176 | |||
| 177 | fclose(f); | ||
| 178 | return r; | ||
| 179 | } | ||
| 180 | |||
| 181 | /* Public functions **********************************************************/ | ||
| 182 | |||
| 183 | Cube | ||
| 184 | apply_trans(Trans t, Cube cube) | ||
| 185 | { | ||
| 186 | /*init_trans();*/ | ||
| 187 | |||
| 188 | int aux_epos[3] = { cube.epose, cube.eposs, cube.eposm }; | ||
| 189 | int aux_eo[3] = { cube.eoud, cube.eorl, cube.eofb }; | ||
| 190 | int aux_co[3] = { cube.coud, cube.corl, cube.cofb }; | ||
| 191 | |||
| 192 | return (Cube) { | ||
| 193 | .epose = epose_ttable[t][aux_epos[epose_source[t]]], | ||
| 194 | .eposs = eposs_ttable[t][aux_epos[eposs_source[t]]], | ||
| 195 | .eposm = eposm_ttable[t][aux_epos[eposm_source[t]]], | ||
| 196 | .eofb = eo_ttable[t][aux_eo[eofb_source[t]]], | ||
| 197 | .eorl = eo_ttable[t][aux_eo[eorl_source[t]]], | ||
| 198 | .eoud = eo_ttable[t][aux_eo[eoud_source[t]]], | ||
| 199 | .coud = co_ttable[t][aux_co[coud_source[t]]], | ||
| 200 | .corl = co_ttable[t][aux_co[corl_source[t]]], | ||
| 201 | .cofb = co_ttable[t][aux_co[cofb_source[t]]], | ||
| 202 | .cp = cp_ttable[t][cube.cp], | ||
| 203 | .cpos = cpos_ttable[t][cube.cpos] | ||
| 204 | }; | ||
| 205 | } | 59 | } |
| 206 | 60 | ||
| 61 | /* | ||
| 207 | Trans | 62 | Trans |
| 208 | inverse_trans(Trans t) | 63 | inverse_trans(Trans t) |
| 209 | { | 64 | { |
| @@ -231,23 +86,18 @@ inverse_trans(Trans t) | |||
| 231 | 86 | ||
| 232 | return inverse_trans_aux[t]; | 87 | return inverse_trans_aux[t]; |
| 233 | } | 88 | } |
| 89 | */ | ||
| 234 | 90 | ||
| 235 | Alg * | 91 | Trans |
| 236 | rotation_alg(Trans t) | 92 | inverse_trans(Trans t) |
| 237 | { | 93 | { |
| 238 | int i; | 94 | return trans_itable[t]; |
| 239 | 95 | } | |
| 240 | static Alg *rotation_alg_arr[NROTATIONS]; | ||
| 241 | static bool initialized = false; | ||
| 242 | |||
| 243 | if (!initialized) { | ||
| 244 | for (i = 0; i < NROTATIONS; i++) | ||
| 245 | rotation_alg_arr[i] = new_alg(rotation_alg_string[i]); | ||
| 246 | |||
| 247 | initialized = true; | ||
| 248 | } | ||
| 249 | 96 | ||
| 250 | return rotation_alg_arr[t % NROTATIONS]; | 97 | Alg * |
| 98 | rotation_alg(Trans i) | ||
| 99 | { | ||
| 100 | return rotation_alg_arr[i % NROTATIONS]; | ||
| 251 | } | 101 | } |
| 252 | 102 | ||
| 253 | void | 103 | void |
| @@ -255,10 +105,20 @@ transform_alg(Trans t, Alg *alg) | |||
| 255 | { | 105 | { |
| 256 | int i; | 106 | int i; |
| 257 | 107 | ||
| 258 | /*init_trans();*/ | ||
| 259 | |||
| 260 | for (i = 0; i < alg->len; i++) | 108 | for (i = 0; i < alg->len; i++) |
| 261 | alg->move[i] = moves_ttable[t][alg->move[i]]; | 109 | alg->move[i] = transform_move(t, alg->move[i]); |
| 110 | } | ||
| 111 | |||
| 112 | Move | ||
| 113 | transform_move(Trans t, Move m) | ||
| 114 | { | ||
| 115 | return moves_ttable[t][m]; | ||
| 116 | } | ||
| 117 | |||
| 118 | Trans | ||
| 119 | transform_trans(Trans t, Trans m) | ||
| 120 | { | ||
| 121 | return trans_ttable[t][m]; | ||
| 262 | } | 122 | } |
| 263 | 123 | ||
| 264 | void | 124 | void |
| @@ -268,106 +128,63 @@ init_trans() { | |||
| 268 | return; | 128 | return; |
| 269 | initialized = true; | 129 | initialized = true; |
| 270 | 130 | ||
| 271 | init_moves(); | 131 | int i; |
| 272 | 132 | Alg *nonsym_alg, *nonsym_inv; | |
| 273 | Cube aux, cube, c[3]; | 133 | Cube aux, cube; |
| 274 | CubeArray epcp; | ||
| 275 | int i, eparr[12], eoarr[12], cparr[8], coarr[8]; | ||
| 276 | unsigned int ui; | ||
| 277 | Move mi, move; | 134 | Move mi, move; |
| 278 | Trans m; | 135 | Trans t, u, v; |
| 279 | 136 | ||
| 280 | /* Compute sources */ | 137 | init_moves(); |
| 281 | for (i = 0; i < NTRANS; i++) { | ||
| 282 | cube = apply_alg(rotation_alg(i), (Cube){0}); | ||
| 283 | |||
| 284 | epose_source[i] = edge_slice(what_edge_at(cube, FR)); | ||
| 285 | eposs_source[i] = edge_slice(what_edge_at(cube, UR)); | ||
| 286 | eposm_source[i] = edge_slice(what_edge_at(cube, UF)); | ||
| 287 | eofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 288 | eorl_source[i] = what_center_at(cube, R_center)/2; | ||
| 289 | eoud_source[i] = what_center_at(cube, U_center)/2; | ||
| 290 | coud_source[i] = what_center_at(cube, U_center)/2; | ||
| 291 | cofb_source[i] = what_center_at(cube, F_center)/2; | ||
| 292 | corl_source[i] = what_center_at(cube, R_center)/2; | ||
| 293 | } | ||
| 294 | |||
| 295 | if (read_ttables_file()) | ||
| 296 | return; | ||
| 297 | |||
| 298 | fprintf(stderr, "Cannot load %s, generating it\n", "ttables"); | ||
| 299 | |||
| 300 | /* Initialize tables */ | ||
| 301 | for (m = 0; m < NTRANS; m++) { | ||
| 302 | epcp = (CubeArray){ .ep = eparr, .cp = cparr }; | ||
| 303 | cube = apply_alg(rotation_alg(m), (Cube){0}); | ||
| 304 | cube_to_arrays(cube, &epcp, pf_epcp); | ||
| 305 | if (m >= NROTATIONS) { | ||
| 306 | apply_permutation(ep_mirror, eparr, 12); | ||
| 307 | apply_permutation(cp_mirror, cparr, 8); | ||
| 308 | } | ||
| 309 | |||
| 310 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 311 | c[0] = admissible_ep((Cube){ .epose = ui }, pf_e); | ||
| 312 | c[1] = admissible_ep((Cube){ .eposs = ui }, pf_s); | ||
| 313 | c[2] = admissible_ep((Cube){ .eposm = ui }, pf_m); | ||
| 314 | |||
| 315 | cube = rotate_via_compose(m,c[epose_source[m]],pf_ep); | ||
| 316 | epose_ttable[m][ui] = cube.epose; | ||
| 317 | 138 | ||
| 318 | cube = rotate_via_compose(m,c[eposs_source[m]],pf_ep); | 139 | for (i = 0; i < NROTATIONS; i++) |
| 319 | eposs_ttable[m][ui] = cube.eposs; | 140 | rotation_alg_arr[i] = new_alg(rotation_alg_string[i]); |
| 320 | 141 | ||
| 321 | cube = rotate_via_compose(m,c[eposm_source[m]],pf_ep); | 142 | for (t = 0; t < NTRANS; t++) { |
| 322 | eposm_ttable[m][ui] = cube.eposm; | ||
| 323 | } | ||
| 324 | for (ui = 0; ui < POW2TO11; ui++ ) { | ||
| 325 | int_to_sum_zero_array(ui, 2, 12, eoarr); | ||
| 326 | apply_permutation(eparr, eoarr, 12); | ||
| 327 | eo_ttable[m][ui] = digit_array_to_int(eoarr, 11, 2); | ||
| 328 | } | ||
| 329 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 330 | int_to_sum_zero_array(ui, 3, 8, coarr); | ||
| 331 | apply_permutation(cparr, coarr, 8); | ||
| 332 | co_ttable[m][ui] = digit_array_to_int(coarr, 7, 3); | ||
| 333 | if (m >= NROTATIONS) | ||
| 334 | co_ttable[m][ui] = | ||
| 335 | invert_digits(co_ttable[m][ui], 3, 7); | ||
| 336 | } | ||
| 337 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 338 | cube = (Cube){ .cp = ui }; | ||
| 339 | cube = rotate_via_compose(m, cube, pf_cp); | ||
| 340 | cp_ttable[m][ui] = cube.cp; | ||
| 341 | } | ||
| 342 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 343 | cube = (Cube){ .cpos = ui }; | ||
| 344 | cube = rotate_via_compose(m, cube, pf_cpos); | ||
| 345 | cpos_ttable[m][ui] = cube.cpos; | ||
| 346 | } | ||
| 347 | for (mi = 0; mi < NMOVES; mi++) { | 143 | for (mi = 0; mi < NMOVES; mi++) { |
| 348 | /* Old version: | 144 | make_solved(&aux); |
| 349 | * | 145 | apply_move(mi, &aux); |
| 350 | aux = apply_trans(m, apply_move(mi, (Cube){0})); | 146 | apply_trans(t, &aux); |
| 351 | for (move = 0; move < NMOVES; move++) { | 147 | for (move = 0; move < NMOVES; move++) { |
| 352 | cube = apply_move(inverse_move(move), aux); | 148 | copy_cube(&aux, &cube); |
| 353 | mirr = apply_trans(uf_mirror, cube); | 149 | apply_move(inverse_move(move), &cube); |
| 354 | if (is_solved(cube) || is_solved(mirr)) | 150 | if (is_solved(&cube)) { |
| 355 | moves_ttable[m][mi] = move; | 151 | moves_ttable[t][mi] = move; |
| 152 | break; | ||
| 153 | } | ||
| 356 | } | 154 | } |
| 357 | */ | 155 | } |
| 156 | } | ||
| 358 | 157 | ||
| 359 | aux = apply_trans(m, apply_move(mi, (Cube){0})); | 158 | nonsym_alg = new_alg("R' U' F"); |
| 360 | for (move = 0; move < NMOVES; move++) { | 159 | nonsym_inv = inverse_alg(nonsym_alg); |
| 361 | cube = apply_move(inverse_move(move), aux); | 160 | |
| 362 | if (is_solved(cube)) { | 161 | for (t = 0; t < NTRANS; t++) { |
| 363 | moves_ttable[m][mi] = move; | 162 | for (u = 0; u < NTRANS; u++) { |
| 163 | make_solved(&aux); | ||
| 164 | apply_alg(nonsym_alg, &aux); | ||
| 165 | apply_trans(u, &aux); | ||
| 166 | apply_trans(t, &aux); | ||
| 167 | for (v = 0; v < NTRANS; v++) { | ||
| 168 | copy_cube(&aux, &cube); | ||
| 169 | apply_trans(v, &cube); | ||
| 170 | apply_alg(nonsym_inv, &cube); | ||
| 171 | if (is_solved(&cube)) { | ||
| 172 | /* This is the inverse of the correct | ||
| 173 | value, it will be inverted later */ | ||
| 174 | trans_ttable[t][u] = v; | ||
| 175 | if (v == uf) | ||
| 176 | trans_itable[t] = u; | ||
| 364 | break; | 177 | break; |
| 365 | } | 178 | } |
| 366 | } | 179 | } |
| 367 | } | 180 | } |
| 368 | } | 181 | } |
| 182 | for (t = 0; t < NTRANS; t++) | ||
| 183 | for (u = 0; u < NTRANS; u++) | ||
| 184 | trans_ttable[t][u] = trans_itable[trans_ttable[t][u]]; | ||
| 185 | |||
| 369 | 186 | ||
| 370 | if (!write_ttables_file()) | 187 | free_alg(nonsym_alg); |
| 371 | fprintf(stderr, "Error writing ttables\n"); | 188 | free_alg(nonsym_inv); |
| 372 | } | 189 | } |
| 373 | 190 | ||
diff --git a/src/trans.h b/src/trans.h index 51df12f..0cc8cef 100644 --- a/src/trans.h +++ b/src/trans.h | |||
| @@ -3,24 +3,30 @@ | |||
| 3 | 3 | ||
| 4 | #include "moves.h" | 4 | #include "moves.h" |
| 5 | 5 | ||
| 6 | /* | 6 | void apply_trans(Trans t, Cube *cube); |
| 7 | * Tables are exposed to allow faster partial transformations in some | ||
| 8 | * specific cases (in symcoord) | ||
| 9 | */ | ||
| 10 | extern int epose_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 11 | extern int eposs_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 12 | extern int eposm_ttable[NTRANS][FACTORIAL12/FACTORIAL8]; | ||
| 13 | extern int eo_ttable[NTRANS][POW2TO11]; | ||
| 14 | extern int cp_ttable[NTRANS][FACTORIAL8]; | ||
| 15 | extern int co_ttable[NTRANS][POW3TO7]; | ||
| 16 | extern int cpos_ttable[NTRANS][FACTORIAL6]; | ||
| 17 | extern Move moves_ttable[NTRANS][NMOVES]; | ||
| 18 | |||
| 19 | Cube apply_trans(Trans t, Cube cube); | ||
| 20 | Trans inverse_trans(Trans t); | 7 | Trans inverse_trans(Trans t); |
| 21 | Alg * rotation_alg(Trans i); | 8 | Alg * rotation_alg(Trans i); |
| 22 | void transform_alg(Trans i, Alg *alg); | 9 | void transform_alg(Trans t, Alg *alg); |
| 10 | Move transform_move(Trans t, Move m); | ||
| 11 | Trans transform_trans(Trans t, Trans m); | ||
| 23 | 12 | ||
| 24 | void init_trans(); | 13 | void init_trans(); |
| 25 | 14 | ||
| 15 | #ifndef TRANS_C | ||
| 16 | |||
| 17 | extern TransGroup tgrp_udfix; | ||
| 18 | |||
| 19 | #else | ||
| 20 | |||
| 21 | TransGroup | ||
| 22 | tgrp_udfix = { | ||
| 23 | .n = 16, | ||
| 24 | .t = { uf, ur, ub, ul, | ||
| 25 | df, dr, db, dl, | ||
| 26 | uf_mirror, ur_mirror, ub_mirror, ul_mirror, | ||
| 27 | df_mirror, dr_mirror, db_mirror, dl_mirror }, | ||
| 28 | }; | ||
| 29 | |||
| 30 | #endif | ||
| 31 | |||
| 26 | #endif | 32 | #endif |
diff --git a/src/utils.c b/src/utils.c index e0d3268..cbf951e 100644 --- a/src/utils.c +++ b/src/utils.c | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | #define UTILS_C | ||
| 2 | |||
| 1 | #include "utils.h" | 3 | #include "utils.h" |
| 2 | 4 | ||
| 3 | void | 5 | void |
| @@ -159,24 +161,24 @@ is_perm(int *a, int n) | |||
| 159 | { | 161 | { |
| 160 | int *aux = malloc(n * sizeof(int)); | 162 | int *aux = malloc(n * sizeof(int)); |
| 161 | int i; | 163 | int i; |
| 164 | bool ret = true; | ||
| 162 | 165 | ||
| 163 | for (i = 0; i < n; i++) | 166 | for (i = 0; i < n; i++) |
| 164 | aux[i] = 0; | 167 | aux[i] = 0; |
| 165 | 168 | ||
| 166 | for (i = 0; i < n; i++) { | 169 | for (i = 0; i < n; i++) { |
| 167 | if (a[i] < 0 || a[i] >= n) | 170 | if (a[i] < 0 || a[i] >= n) |
| 168 | return false; | 171 | ret = false; |
| 169 | else | 172 | else |
| 170 | aux[a[i]] = 1; | 173 | aux[a[i]] = 1; |
| 171 | } | 174 | } |
| 172 | 175 | ||
| 173 | for (i = 0; i < n; i++) | 176 | for (i = 0; i < n; i++) |
| 174 | if (!aux[i]) | 177 | if (!aux[i]) |
| 175 | return false; | 178 | ret = false; |
| 176 | 179 | ||
| 177 | free(aux); | 180 | free(aux); |
| 178 | 181 | return ret; | |
| 179 | return true; | ||
| 180 | } | 182 | } |
| 181 | 183 | ||
| 182 | bool | 184 | bool |
| @@ -195,7 +197,7 @@ perm_sign(int *a, int n) | |||
| 195 | { | 197 | { |
| 196 | int i, j, ret = 0; | 198 | int i, j, ret = 0; |
| 197 | 199 | ||
| 198 | if (!is_perm(a,n)) | 200 | if (!is_perm(a, n)) |
| 199 | return -1; | 201 | return -1; |
| 200 | 202 | ||
| 201 | for (i = 0; i < n; i++) | 203 | for (i = 0; i < n; i++) |
| @@ -211,7 +213,7 @@ perm_to_index(int *a, int n) | |||
| 211 | int i, j, c, ret = 0; | 213 | int i, j, c, ret = 0; |
| 212 | 214 | ||
| 213 | if (!is_perm(a, n)) | 215 | if (!is_perm(a, n)) |
| 214 | return -1; | 216 | return factorial(n); |
| 215 | 217 | ||
| 216 | for (i = 0; i < n; i++) { | 218 | for (i = 0; i < n; i++) { |
| 217 | c = 0; | 219 | c = 0; |
diff --git a/www/download/index.html b/www/download/index.html index b115244..01c4895 100644 --- a/www/download/index.html +++ b/www/download/index.html | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | <html lang="en"> | 2 | <html lang="en"> |
| 3 | <head> | 3 | <head> |
| 4 | <title> Download | Nissy </title> | 4 | <title> Download | Nissy </title> |
| 5 | <meta name="viewport" content="width=device-width" /> <link rel="stylesheet" type="text/css" href="/style.css"> | 5 | <meta name="viewport" content="width=device-width" /> <link rel="stylesheet" type="text/css" href="/style-3.css"> |
| 6 | <link rel="icon" href="/favicon.png"> | 6 | <link rel="icon" href="/favicon.png"> |
| 7 | <meta charset="utf-8"> | 7 | <meta charset="utf-8"> |
| 8 | </head> | 8 | </head> |
diff --git a/www/examples/index.html b/www/examples/index.html index 24eda85..517c251 100644 --- a/www/examples/index.html +++ b/www/examples/index.html | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | <html lang="en"> | 2 | <html lang="en"> |
| 3 | <head> | 3 | <head> |
| 4 | <title> Examples | Nissy </title> | 4 | <title> Examples | Nissy </title> |
| 5 | <meta name="viewport" content="width=device-width" /> <link rel="stylesheet" type="text/css" href="/style.css"> | 5 | <meta name="viewport" content="width=device-width" /> <link rel="stylesheet" type="text/css" href="/style-3.css"> |
| 6 | <link rel="icon" href="/favicon.png"> | 6 | <link rel="icon" href="/favicon.png"> |
| 7 | <meta charset="utf-8"> | 7 | <meta charset="utf-8"> |
| 8 | </head> | 8 | </head> |
diff --git a/www/index.html b/www/index.html index 0b7e67e..500952c 100644 --- a/www/index.html +++ b/www/index.html | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | <html lang="en"> | 2 | <html lang="en"> |
| 3 | <head> | 3 | <head> |
| 4 | <title> Nissy | Nissy </title> | 4 | <title> Nissy | Nissy </title> |
| 5 | <meta name="viewport" content="width=device-width" /> <link rel="stylesheet" type="text/css" href="/style.css"> | 5 | <meta name="viewport" content="width=device-width" /> <link rel="stylesheet" type="text/css" href="/style-3.css"> |
| 6 | <link rel="icon" href="/favicon.png"> | 6 | <link rel="icon" href="/favicon.png"> |
| 7 | <meta charset="utf-8"> | 7 | <meta charset="utf-8"> |
| 8 | </head> | 8 | </head> |
diff --git a/www/style.css b/www/style-2.css index 1487497..ec70635 100644 --- a/www/style.css +++ b/www/style-2.css | |||
| @@ -32,11 +32,17 @@ img { | |||
| 32 | max-width: 100%; | 32 | max-width: 100%; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | pre, code { | 35 | code { |
| 36 | background-color: #eeeeee; | 36 | background-color: #eeeeee; |
| 37 | padding: 2px; | ||
| 38 | } | ||
| 39 | |||
| 40 | pre code { | ||
| 41 | padding: 0px; | ||
| 37 | } | 42 | } |
| 38 | 43 | ||
| 39 | pre { | 44 | pre { |
| 45 | background-color: #eeeeee; | ||
| 40 | border: 2px solid; | 46 | border: 2px solid; |
| 41 | padding: 6px; | 47 | padding: 6px; |
| 42 | } | 48 | } |
