/* This is libnissy (temporarily also known as h48), a Rubik's cube library. All the functions return 0 or a positive integer in case of success and a negative integer in case of error, unless otherwise specified. See below for the list of error codes and their meaning. Cubes are passed as strings in the cccccccc=eeeeeeeeeeee=r format, see the README.md file for more information. Accepted moves are any of the following: U, D, R, L, F, B, Uw, Dw, Rw, Lw, Fw, Bw, M, S, E, x, y, z optionally followed by a 2, a ' or a 3. The standard NISS notation is also accepted: moves in parentheses () are inverted and used as premoves. A transformation must be given in the format (rotation|mirrored) (2 letters) for example 'rotation UF' or 'mirrored BL'. */ /* Constants *****************************************************************/ /* Some constants for size for I/O buffers */ #define NISSY_SIZE_CUBE 24U #define NISSY_SIZE_TRANSFORMATION 12U #define NISSY_SIZE_SOLVE_STATS 10U #define NISSY_SIZE_DATAID 255U #define NISSY_SIZE_MOVES 1000U /* Flags for NISS options */ #define NISSY_NISSFLAG_NORMAL 1U #define NISSY_NISSFLAG_INVERSE 2U #define NISSY_NISSFLAG_MIXED 4U #define NISSY_NISSFLAG_LINEAR \ (NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE) #define NISSY_NISSFLAG_ALL \ (NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE | NISSY_NISSFLAG_MIXED) /* Status for stopping / pausing / resuming a solver */ #define NISSY_STATUS_RUN 0 #define NISSY_STATUS_STOP 1 #define NISSY_STATUS_PAUSE 2 /* Possible results of move sequence comparison */ #define NISSY_COMPARE_MOVES_EQUAL 0 #define NISSY_COMPARE_MOVES_DIFFERENT 99 /* The solved cube */ #define NISSY_SOLVED_CUBE "ABCDEFGH=ABCDEFGHIJKL=A" /* Error codes ***************************************************************/ /* The value NISSY_OK denotes a success. If returned by solve, it means that no solution has been found. */ #define NISSY_OK 0LL /* The value NISSY_WARNING_UNSOLVABLE is a warning. It means that the operation was completed succesfully, but the resulting cube is in an unsolvable state. This could be intended, for example if the user has provided an unsolvable cube as input. */ #define NISSY_WARNING_UNSOLVABLE -1LL /* The value NISSY_ERROR_INVALID_CUBE means that the provided cube is invalid. It could be written in an unknown format, or be ill-formed. */ #define NISSY_ERROR_INVALID_CUBE -10LL /* The value NISSY_ERROR_UNSOLVABLE_CUBE means that the provided cube is in an unsolvable state for the given solver. This could mean either that the cube is not solvable at all (for example in case it has a single twisted corner), or that it is not ready for the given step (for example if the caller wants to solve a DR finish without the cube being in DR state). */ #define NISSY_ERROR_UNSOLVABLE_CUBE -11LL /* The value NISSY_ERROR_INVALID_MOVES means that the given moves are invalid. */ #define NISSY_ERROR_INVALID_MOVES -20LL /* The value NISSY_ERROR_INVALID_TRANS means that the given transformation is invalid. */ #define NISSY_ERROR_INVALID_TRANS -30LL /* The value NISSY_ERROR_INVALID_SOLVER means that the given solver is not known. */ #define NISSY_ERROR_INVALID_SOLVER -50LL /* The value NISSY_ERROR_INVALID_VARIATION means that the given method of finding variations for a solution is not known. */ #define NISSY_ERROR_INVALID_VARIATION -51LL /* The value NISSY_ERROR_NULL_POINTER means that one of the provided pointer arguments is NULL. For example, it may be returned by solve when called with a solver that requires some pre-computed data, but the provided data is NULL. */ #define NISSY_ERROR_NULL_POINTER -60LL /* The value NISSY_ERROR_BUFFER_SIZE means that one of the buffers provided is too small. For example, it could be too small to hold the result or too small to hold the data generated by gendata. */ #define NISSY_ERROR_BUFFER_SIZE -61LL /* The value NISSY_ERROR_DATA means that the provided data is invalid. For example, it may be returned by solve when called with incompatible solver and data arguments. */ #define NISSY_ERROR_DATA -70LL /* The value NISSY_ERROR_OPTIONS means that one or more of the given options are invalid. For example, it may be returned by solve when called with a negative maximum number of solutions. */ #define NISSY_ERROR_OPTIONS -80LL /* The value NISSY_ERROR_UNKNOWN denotes an unexpected error. It probably means that there some bug in this library. If you can, report any error of this kind to sebastiano@tronto.net. Thanks! */ #define NISSY_ERROR_UNKNOWN -999LL /* Library functions *********************************************************/ /* Compute the inverse of the given cube. Parameters: cube - The cube to be inverted. result - The return parameter for the resulting cube. Return values: NISSY_OK - The cube was inverted succesfully. NISSY_WARNING_UNSOLVABLE - The resulting cube is not solvable. This is either because the given cube was not solvable, or due to an unknown internal error. NISSY_ERROR_INVALID_CUBE - The given cube is invalid. NISSY_ERROR_UNKNOWN - An unknown error occurred. */ long long nissy_inverse( const char cube[static NISSY_SIZE_CUBE], char result[static NISSY_SIZE_CUBE] ); /* Apply the given sequence of moves on the given cube. Parameters: cube - The cube to move. moves - The moves to apply to the cube. Must be a NULL-terminated string. result - The return parameter for the resulting cube. Return values: NISSY_OK - The moves were applied succesfully. NISSY_WARNING_UNSOLVABLE - The resulting cube is not solvable. This is either because the given cube was not solvable, or due to an unknown internal error. NISSY_ERROR_INVALID_CUBE - The given cube is invalid. NISSY_ERROR_INVALID_MOVES - The given moves are invalid. NISSY_ERROR_NULL_POINTER - The 'moves' argument is NULL. */ long long nissy_applymoves( const char cube[static NISSY_SIZE_CUBE], const char *moves, char result[static NISSY_SIZE_CUBE] ); /* Apply the single given transformation to the given cube. Parameters: cube - The cube to be transformed. transformation - The transformation in "(rotation|mirrored) __" format. result - The return parameter for the resulting cube. Return values: NISSY_OK - The transformation was performed succesfully. NISSY_WARNING_UNSOLVABLE - The resulting cube is not solvable. This is probably due to an unknown internal error. NISSY_ERROR_INVALID_CUBE - The given cube is invalid. NISSY_ERROR_INVALID_TRANS - The given transformation is invalid. */ long long nissy_applytrans( const char cube[static NISSY_SIZE_CUBE], const char transformation[static NISSY_SIZE_TRANSFORMATION], char result[static NISSY_SIZE_CUBE] ); /* Find variations of a given move sequence, for example by changing the direction of the last quarter turn(s), or linearizing a NISS move sequence. The result consists of one or more move sequences, one per line, and it always ends in a newline character. Parameters: moves - The moves of which to find the variation. Must be at most NISSY_SIZE_MOVES long. variations - Specify which kind of variations to find, for example "lastqt" or "unniss". result_size - The size of the result buffer. result - The result buffer. Return values: NISSY_ERROR_NULL_POINTER - One of the provided pointers is NULL. NISSY_ERROR_INVALID_MOVES - The given moves are invalid. NISSY_ERROR_INVALID_VARIATION - The given transformer is not known. NISSY_ERROR_BUFFER_SIZE - Either the result buffer is too small or the given move sequence is longer than NISSY_SIZE_MOVES. Any value >= 0 - The number of variations found. */ long long nissy_variations( const char *moves, const char *variation, unsigned long long result_size, char *result ); /* Get the cube with the given ep, eo, cp and co values. The values must be in the ranges specified below, but if the option "fix" is given any values outside its range will be adjusted before using it. The option "fix" also fixes parity and orientation issues, resulting always in a solvable cube. Parameters: ep - The edge permutation, 0 <= ep < 479001600 (12!) eo - The edge orientation, 0 <= eo < 2047 (2^11) cp - The corner permutation, 0 <= cp < 40320 (8!) co - The corner orientation, 0 <= co < 2187 (3^7) orient - The orientation of the cube, 0 <= orient < 24 options - Other options. result - The return parameter for the resulting cube. Return values: NISSY_OK - The cube was generated succesfully. NISSY_WARNING_UNSOLVABLE - The resulting cube is unsolvable. NISSY_ERROR_OPTIONS - One or more of the given parameters is invalid. */ long long nissy_getcube( long long ep, long long eo, long long cp, long long co, long long orient, const char *options, char result[static NISSY_SIZE_CUBE] ); /* Compute the size of the data generated by nissy_gendata when called for the given solver, and other useful information. Parameters: solver - The name of the solver. dataid - An identifier for the data computed for the solver. Different solvers may use equivalent data. This identifier can be used e.g. as a filename or database key to save and retrieve the correct data for each solver, without duplication. Return values: NISSY_ERROR_INVALID_SOLVER - The given solver is not known. NISSY_ERROR_NULL_POINTER - The 'solver' argument is null. NISSY_ERROR_UNKNOWN - An unknown error occurred. Any value >= 0 - The size of the data, in bytes. */ long long nissy_solverinfo( const char *solver, char dataid[static NISSY_SIZE_DATAID] ); /* Compute the data for the given solver and store it in generated_data. Parameters: solver - The name of the solver. data_size - The size of the data buffer. It is advised to use nissy_solverinfo to check how much memory is needed. data - The return parameter for the generated data. This buffer must have 8-byte alignment. Return values: NISSY_ERROR_INVALID_SOLVER - The given solver is not known. NISSY_ERROR_NULL_POINTER - The 'solver' argument is null. NISSY_ERROR_UNKNOWN - An error occurred while generating the data. NISSY_ERROR_DATA - The data buffer is invalid, for example because it is not 8-byte aligned. Any value >= 0 - The size of the data, in bytes. */ long long nissy_gendata( const char *solver, unsigned long long data_size, unsigned char *data ); /* Check that the data is a valid data table for a solver. Parameters: solver - The name of the solver. data_size - The size of the data buffer. data - The data for the solver. Can be computed with gendata. This buffer must have 8-byte alignment. Return values: NISSY_OK - The data is valid. NISSY_ERROR_DATA - The data is invalid. */ long long nissy_checkdata( const char *solver, unsigned long long data_size, const unsigned char *data ); /* Solve the given cube using the given solver and options. Parameters: cube - The cube to solver. solver - The name of the solver. See doc/solvers.md for a list. nissflag - The flags for NISS (linear, inverse, mixed, or combinations; see the constants at the top of this file). minmoves - The minimum number of moves for a solution. maxmoves - The maximum number of moves for a solution. maxsols - The maximum number of solutions. optimal - The maximum number of moves above the optimal solution. threads - The number of threads to use. Must be less than or equal to the value of the compile-time constant THREADS. If set to 0, the default value THREADS will be used. data_size - The size of the data buffer. data - The data for the solver. Can be computed with gendata. This buffer must have 8-byte alignment. sols_size - The size of the solutions buffer. sols - The return parameter for the solutions. The solutions are separated by a '\n' (newline) and a '\0' (NULL character) terminates the list. stats - An array to store some statistics about the solve. poll_status - A callback function that should return the current requested status for the solver (e.g. run, stop, pause, resume; see the constants at the top of this file). The way this status is polled and honored is solver-specific. If this parameter is NULL, the status will always assumed to be "run". poll_status_data - Auxiliary data for the poll_status callback function. Return values: NISSY_OK - Cube solved succesfully. NISSY_ERROR_INVALID_CUBE - The given cube is invalid. NISSY_ERROR_UNSOLVABLE_CUBE - The given cube is valid, but not solvable with the given solver. NISSY_ERROR_OPTIONS - One or more of the given options are invalid. NISSY_ERROR_INVALID_SOLVER - The given solver is not known. NISSY_ERROR_NULL_POINTER - The 'solver' argument is null. NISSY_ERROR_DATA - The data buffer is invalid. Any value >= 0 - The number of solutions found. */ long long nissy_solve( const char cube[static NISSY_SIZE_CUBE], const char *solver, unsigned nissflag, unsigned minmoves, unsigned maxmoves, unsigned maxsolutions, unsigned optimal, unsigned threads, unsigned long long data_size, const unsigned char *data, unsigned sols_size, char *sols, long long stats[static NISSY_SIZE_SOLVE_STATS], int (*poll_status)(void *), void *poll_status_data ); /* Count the given moves. Parameters: moves - The moves to be counted. Return values: NISSY_ERROR_INVALID_MOVES - The given moves are invalid. NISSY_ERROR_NULL_POINTER - The 'moves' argument is NULL. Any value >= 0 - The number of moves. */ long long nissy_countmoves( const char *moves ); /* Compare the two moves sequences. Both must be at most NISSY_SIZE_MOVES long. Parameters: moves1 - The first sequence of moves to compare. moves2 - The second sequence of moves to compare. Return values: NISSY_ERROR_INVALID_MOVES - One of the given moves sequences is invalid. NISSY_ERROR_NULL_POINTER - One of the arguments is NULL. NISSY_COMPARE_MOVES_EQUAL - The two moves sequences are indentical, up to swapping parallel moves. NISSY_COMPARE_MOVES_DIFFERENT - The two moves sequences are different. */ long long nissy_comparemoves( const char *moves1, const char *moves2 ); /* Set a global logger function used by this library. Setting the logger to NULL disables logging. Parameters: logger_function - A pointer to a function that takes two parameters: * A C string, the string to be printed. * Any other data via a void pointer. user_data - Any data that will be provided by the logger when calling logger_function. Return values: NISSY_OK - Logger set succesfully. No warning or error is going to be given if the logger is invalid. */ long long nissy_setlogger( void (*logger_function)(const char *, void *), void *user_data );