diff options
Diffstat (limited to '')
| -rw-r--r-- | shell.c | 56 | ||||
| -rw-r--r-- | src/core/cube.h | 14 | ||||
| -rw-r--r-- | src/core/io_cube.h | 62 | ||||
| -rw-r--r-- | src/core/io_trans.h | 1 | ||||
| -rw-r--r-- | src/core/moves.h | 24 | ||||
| -rw-r--r-- | src/core/transform.h | 6 | ||||
| -rw-r--r-- | src/nissy.c | 63 | ||||
| -rw-r--r-- | src/nissy.h | 120 | ||||
| -rw-r--r-- | tools/nissy_extra.h | 1 |
9 files changed, 228 insertions, 119 deletions
| @@ -56,9 +56,6 @@ typedef struct { | |||
| 56 | int64_t maxsolutions; | 56 | int64_t maxsolutions; |
| 57 | } args_t; | 57 | } args_t; |
| 58 | 58 | ||
| 59 | static void print_cube_result(int64_t, char [static 22]); | ||
| 60 | static void print_str_result(int64_t, char *); | ||
| 61 | |||
| 62 | static int64_t compose_exec(args_t *); | 59 | static int64_t compose_exec(args_t *); |
| 63 | static int64_t inverse_exec(args_t *); | 60 | static int64_t inverse_exec(args_t *); |
| 64 | static int64_t applymoves_exec(args_t *); | 61 | static int64_t applymoves_exec(args_t *); |
| @@ -240,36 +237,6 @@ rand64(void) | |||
| 240 | return ret; | 237 | return ret; |
| 241 | } | 238 | } |
| 242 | 239 | ||
| 243 | static void | ||
| 244 | print_cube_result(int64_t ret, char result[static 22]) | ||
| 245 | { | ||
| 246 | switch (ret) { | ||
| 247 | case 0: | ||
| 248 | break; | ||
| 249 | case 1: | ||
| 250 | fprintf(stderr, "Warning: resulting cube not solvable\n"); | ||
| 251 | break; | ||
| 252 | case 2: /* Fallthrough */ | ||
| 253 | default: | ||
| 254 | fprintf(stderr, "Unknown error (result is inconsistent)\n"); | ||
| 255 | } | ||
| 256 | |||
| 257 | printf("%s\n", result); | ||
| 258 | } | ||
| 259 | |||
| 260 | static void | ||
| 261 | print_str_result(int64_t ret, char *result) | ||
| 262 | { | ||
| 263 | switch (ret) { | ||
| 264 | case 0: | ||
| 265 | break; | ||
| 266 | default: | ||
| 267 | fprintf(stderr, "Unknown error\n"); | ||
| 268 | } | ||
| 269 | |||
| 270 | printf("%s\n", result); | ||
| 271 | } | ||
| 272 | |||
| 273 | static int64_t | 240 | static int64_t |
| 274 | compose_exec(args_t *args) | 241 | compose_exec(args_t *args) |
| 275 | { | 242 | { |
| @@ -277,7 +244,8 @@ compose_exec(args_t *args) | |||
| 277 | int64_t ret; | 244 | int64_t ret; |
| 278 | 245 | ||
| 279 | ret = nissy_compose(args->cube, args->cube_perm, result); | 246 | ret = nissy_compose(args->cube, args->cube_perm, result); |
| 280 | print_cube_result(ret, result); | 247 | if (ret == 0) |
| 248 | printf("%s\n", result); | ||
| 281 | 249 | ||
| 282 | return ret; | 250 | return ret; |
| 283 | } | 251 | } |
| @@ -289,7 +257,8 @@ inverse_exec(args_t *args) | |||
| 289 | int64_t ret; | 257 | int64_t ret; |
| 290 | 258 | ||
| 291 | ret = nissy_inverse(args->cube, result); | 259 | ret = nissy_inverse(args->cube, result); |
| 292 | print_cube_result(ret, result); | 260 | if (ret == 0) |
| 261 | printf("%s\n", result); | ||
| 293 | 262 | ||
| 294 | return ret; | 263 | return ret; |
| 295 | } | 264 | } |
| @@ -301,7 +270,8 @@ applymoves_exec(args_t *args) | |||
| 301 | int64_t ret; | 270 | int64_t ret; |
| 302 | 271 | ||
| 303 | ret = nissy_applymoves(args->cube, args->str_moves, result); | 272 | ret = nissy_applymoves(args->cube, args->str_moves, result); |
| 304 | print_cube_result(ret, result); | 273 | if (ret == 0) |
| 274 | printf("%s\n", result); | ||
| 305 | 275 | ||
| 306 | return ret; | 276 | return ret; |
| 307 | } | 277 | } |
| @@ -313,7 +283,8 @@ applytrans_exec(args_t *args) | |||
| 313 | int64_t ret; | 283 | int64_t ret; |
| 314 | 284 | ||
| 315 | ret = nissy_applytrans(args->cube, args->str_trans, result); | 285 | ret = nissy_applytrans(args->cube, args->str_trans, result); |
| 316 | print_cube_result(ret, result); | 286 | if (ret == 0) |
| 287 | printf("%s\n", result); | ||
| 317 | 288 | ||
| 318 | return ret; | 289 | return ret; |
| 319 | } | 290 | } |
| @@ -325,7 +296,8 @@ frommoves_exec(args_t *args) | |||
| 325 | int64_t ret; | 296 | int64_t ret; |
| 326 | 297 | ||
| 327 | ret = nissy_frommoves(args->str_moves, result); | 298 | ret = nissy_frommoves(args->str_moves, result); |
| 328 | print_cube_result(ret, result); | 299 | if (ret == 0) |
| 300 | printf("%s\n", result); | ||
| 329 | 301 | ||
| 330 | return ret; | 302 | return ret; |
| 331 | } | 303 | } |
| @@ -338,7 +310,8 @@ convert_exec(args_t *args) | |||
| 338 | 310 | ||
| 339 | ret = nissy_convert( | 311 | ret = nissy_convert( |
| 340 | args->str_format_in, args->str_format_out, args->str_cube, result); | 312 | args->str_format_in, args->str_format_out, args->str_cube, result); |
| 341 | print_str_result(ret, result); | 313 | if (ret == 0) |
| 314 | printf("%s\n", result); | ||
| 342 | 315 | ||
| 343 | return ret; | 316 | return ret; |
| 344 | } | 317 | } |
| @@ -354,7 +327,8 @@ randomcube_exec(args_t *args) | |||
| 354 | cp = rand64(); | 327 | cp = rand64(); |
| 355 | co = rand64(); | 328 | co = rand64(); |
| 356 | ret = nissy_getcube(ep, eo, cp, co, "fix", result); | 329 | ret = nissy_getcube(ep, eo, cp, co, "fix", result); |
| 357 | print_str_result(ret, result); | 330 | if (ret == 0) |
| 331 | printf("%s\n", result); | ||
| 358 | 332 | ||
| 359 | return ret; | 333 | return ret; |
| 360 | } | 334 | } |
| @@ -526,7 +500,7 @@ help_exec(args_t *args) | |||
| 526 | printf("Available commands and usage:\n\n"); | 500 | printf("Available commands and usage:\n\n"); |
| 527 | for (i = 0; commands[i].name != NULL; i++) | 501 | for (i = 0; commands[i].name != NULL; i++) |
| 528 | printf("%-15s%s\n", commands[i].name, commands[i].syn); | 502 | printf("%-15s%s\n", commands[i].name, commands[i].syn); |
| 529 | printf("\nUse 'help COMMAND' for more information.\n"); | 503 | printf("\nUse 'help -command COMMAND' for more information.\n"); |
| 530 | } else { | 504 | } else { |
| 531 | for (i = 0; commands[i].name != NULL; i++) | 505 | for (i = 0; commands[i].name != NULL; i++) |
| 532 | if (!strcmp(args->str_command, commands[i].name)) | 506 | if (!strcmp(args->str_command, commands[i].name)) |
diff --git a/src/core/cube.h b/src/core/cube.h index 2252a85..a3c3e14 100644 --- a/src/core/cube.h +++ b/src/core/cube.h | |||
| @@ -66,16 +66,10 @@ isconsistent(cube_t cube) | |||
| 66 | return true; | 66 | return true; |
| 67 | 67 | ||
| 68 | inconsistent_ep: | 68 | inconsistent_ep: |
| 69 | LOG("Inconsistent EP\n"); | ||
| 70 | return false; | ||
| 71 | inconsistent_cp: | 69 | inconsistent_cp: |
| 72 | LOG("Inconsistent CP\n"); | ||
| 73 | return false; | ||
| 74 | inconsistent_eo: | 70 | inconsistent_eo: |
| 75 | LOG("Inconsistent EO\n"); | ||
| 76 | return false; | ||
| 77 | inconsistent_co: | 71 | inconsistent_co: |
| 78 | LOG("Inconsistent CO\n"); | 72 | /* We used to do more logging here, hence the 4 different labels */ |
| 79 | return false; | 73 | return false; |
| 80 | } | 74 | } |
| 81 | 75 | ||
| @@ -115,13 +109,9 @@ issolvable(cube_t cube) | |||
| 115 | return true; | 109 | return true; |
| 116 | 110 | ||
| 117 | issolvable_parity: | 111 | issolvable_parity: |
| 118 | LOG("EP and CP parities are different\n"); | ||
| 119 | return false; | ||
| 120 | issolvable_eo: | 112 | issolvable_eo: |
| 121 | LOG("Odd number of flipped edges\n"); | ||
| 122 | return false; | ||
| 123 | issolvable_co: | 113 | issolvable_co: |
| 124 | LOG("Sum of corner orientation is not multiple of 3\n"); | 114 | /* We used to do more logging here, hence the 3 different labels */ |
| 125 | return false; | 115 | return false; |
| 126 | } | 116 | } |
| 127 | 117 | ||
diff --git a/src/core/io_cube.h b/src/core/io_cube.h index 9ae82d7..1ac8ec7 100644 --- a/src/core/io_cube.h +++ b/src/core/io_cube.h | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | STATIC cube_t readcube(const char *, const char *); | ||
| 2 | STATIC int writecube(const char *, cube_t, char *); | ||
| 3 | STATIC void log_available_formats(void); | ||
| 1 | STATIC uint8_t readco(const char *); | 4 | STATIC uint8_t readco(const char *); |
| 2 | STATIC uint8_t readcp(const char *); | 5 | STATIC uint8_t readcp(const char *); |
| 3 | STATIC uint8_t readeo(const char *); | 6 | STATIC uint8_t readeo(const char *); |
| @@ -29,7 +32,7 @@ STATIC struct { | |||
| 29 | { .name = "NONE", .read = NULL, .write = NULL }, | 32 | { .name = "NONE", .read = NULL, .write = NULL }, |
| 30 | }; | 33 | }; |
| 31 | 34 | ||
| 32 | cube_t | 35 | STATIC cube_t |
| 33 | readcube(const char *format, const char *buf) | 36 | readcube(const char *format, const char *buf) |
| 34 | { | 37 | { |
| 35 | int i; | 38 | int i; |
| @@ -38,11 +41,12 @@ readcube(const char *format, const char *buf) | |||
| 38 | if (!strcmp(format, ioformat[i].name)) | 41 | if (!strcmp(format, ioformat[i].name)) |
| 39 | return ioformat[i].read(buf); | 42 | return ioformat[i].read(buf); |
| 40 | 43 | ||
| 41 | LOG("Cannot read cube in the given format\n"); | 44 | LOG("Cannot read cube: unknown format '%s'\n", format); |
| 45 | log_available_formats(); | ||
| 42 | return ZERO_CUBE; | 46 | return ZERO_CUBE; |
| 43 | } | 47 | } |
| 44 | 48 | ||
| 45 | void | 49 | STATIC int |
| 46 | writecube(const char *format, cube_t cube, char *buf) | 50 | writecube(const char *format, cube_t cube, char *buf) |
| 47 | { | 51 | { |
| 48 | char *errormsg; | 52 | char *errormsg; |
| @@ -58,18 +62,30 @@ writecube(const char *format, cube_t cube, char *buf) | |||
| 58 | for (i = 0; ioformat[i].write != NULL; i++) { | 62 | for (i = 0; ioformat[i].write != NULL; i++) { |
| 59 | if (!strcmp(format, ioformat[i].name)) { | 63 | if (!strcmp(format, ioformat[i].name)) { |
| 60 | ioformat[i].write(cube, buf); | 64 | ioformat[i].write(cube, buf); |
| 61 | return; | 65 | return 0; |
| 62 | } | 66 | } |
| 63 | } | 67 | } |
| 64 | 68 | ||
| 69 | LOG("Cannot write cube: unknown format '%s'\n", format); | ||
| 70 | log_available_formats(); | ||
| 65 | errormsg = "ERROR: format"; | 71 | errormsg = "ERROR: format"; |
| 66 | 72 | ||
| 67 | writecube_error: | 73 | writecube_error: |
| 68 | LOG("writecube error, see stdout for details\n"); | ||
| 69 | len = strlen(errormsg); | 74 | len = strlen(errormsg); |
| 70 | memcpy(buf, errormsg, len); | 75 | memcpy(buf, errormsg, len); |
| 71 | buf[len] = '\n'; | 76 | buf[len] = '\0'; |
| 72 | buf[len+1] = '\0'; | 77 | return 1; |
| 78 | } | ||
| 79 | |||
| 80 | STATIC void | ||
| 81 | log_available_formats(void) | ||
| 82 | { | ||
| 83 | int i; | ||
| 84 | |||
| 85 | LOG("Available formats: "); | ||
| 86 | for (i = 0; ioformat[i].read != NULL; i++) | ||
| 87 | LOG("'%s' ", ioformat[i].name); | ||
| 88 | LOG("\n"); | ||
| 73 | } | 89 | } |
| 74 | 90 | ||
| 75 | STATIC uint8_t | 91 | STATIC uint8_t |
| @@ -133,14 +149,34 @@ readcube_B32(const char *buf) | |||
| 133 | 149 | ||
| 134 | for (i = 0; i < 8; i++) { | 150 | for (i = 0; i < 8; i++) { |
| 135 | c[i] = b32tocorner(buf[i]); | 151 | c[i] = b32tocorner(buf[i]); |
| 136 | DBG_ASSERT(c[i] < 255, ZERO_CUBE, | 152 | if (c[i] == UINT8_ERROR) { |
| 137 | "Error reading B32 corner %d (char %d)\n", i, i); | 153 | LOG("Error reading B32 corner %d ", i); |
| 154 | if (buf[i] == 0) { | ||
| 155 | LOG("(string terminated early)\n"); | ||
| 156 | } else { | ||
| 157 | LOG("(char '%c')\n", buf[i]); | ||
| 158 | } | ||
| 159 | return ZERO_CUBE; | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | if (buf[8] != '=') { | ||
| 164 | LOG("Error reading B32 separator: a single '=' " | ||
| 165 | "must be used to separate edges and corners\n"); | ||
| 166 | return ZERO_CUBE; | ||
| 138 | } | 167 | } |
| 139 | 168 | ||
| 140 | for (i = 0; i < 12; i++) { | 169 | for (i = 0; i < 12; i++) { |
| 141 | e[i] = b32toedge(buf[i+9]); | 170 | e[i] = b32toedge(buf[i+9]); |
| 142 | DBG_ASSERT(e[i] < 255, ZERO_CUBE, | 171 | if (e[i] == UINT8_ERROR) { |
| 143 | "Error reading B32 edge %d (char %d)\n", i, i+9); | 172 | LOG("Error reading B32 edge %d ", i); |
| 173 | if (buf[i+9] == 0) { | ||
| 174 | LOG("(string terminated early)\n"); | ||
| 175 | } else { | ||
| 176 | LOG("(char '%c')\n", buf[i+9]); | ||
| 177 | } | ||
| 178 | return ZERO_CUBE; | ||
| 179 | } | ||
| 144 | } | 180 | } |
| 145 | 181 | ||
| 146 | return cubefromarray(c, e); | 182 | return cubefromarray(c, e); |
| @@ -314,7 +350,7 @@ STATIC uint8_t | |||
| 314 | b32toedge(char c) | 350 | b32toedge(char c) |
| 315 | { | 351 | { |
| 316 | if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f'))) | 352 | if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f'))) |
| 317 | return 255; | 353 | return UINT8_ERROR; |
| 318 | 354 | ||
| 319 | return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26; | 355 | return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26; |
| 320 | } | 356 | } |
| @@ -324,7 +360,7 @@ b32tocorner(char c) { | |||
| 324 | uint8_t val; | 360 | uint8_t val; |
| 325 | 361 | ||
| 326 | if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f'))) | 362 | if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'f'))) |
| 327 | return 255; | 363 | return UINT8_ERROR; |
| 328 | 364 | ||
| 329 | val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26; | 365 | val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26; |
| 330 | 366 | ||
diff --git a/src/core/io_trans.h b/src/core/io_trans.h index d91e9a2..f4e8ace 100644 --- a/src/core/io_trans.h +++ b/src/core/io_trans.h | |||
| @@ -10,7 +10,6 @@ readtrans(const char *buf) | |||
| 10 | if (!strncmp(buf, transstr[t], 11)) | 10 | if (!strncmp(buf, transstr[t], 11)) |
| 11 | return t; | 11 | return t; |
| 12 | 12 | ||
| 13 | LOG("readtrans error\n"); | ||
| 14 | return UINT8_ERROR; | 13 | return UINT8_ERROR; |
| 15 | } | 14 | } |
| 16 | 15 | ||
diff --git a/src/core/moves.h b/src/core/moves.h index f0d7646..28abc7f 100644 --- a/src/core/moves.h +++ b/src/core/moves.h | |||
| @@ -18,7 +18,7 @@ STATIC cube_t applymoves(cube_t, const char *); | |||
| 18 | STATIC cube_t frommoves(const char *); | 18 | STATIC cube_t frommoves(const char *); |
| 19 | 19 | ||
| 20 | #define FOREACH_READMOVE(ARG_BUF, ARG_MOVE, ARG_C, ARG_MAX, \ | 20 | #define FOREACH_READMOVE(ARG_BUF, ARG_MOVE, ARG_C, ARG_MAX, \ |
| 21 | LABEL_ERROR, ARG_ACTION) \ | 21 | RET_ERROR, ARG_ACTION) \ |
| 22 | const char *VAR_B; \ | 22 | const char *VAR_B; \ |
| 23 | uint8_t VAR_MOVE_NOMOD, VAR_MOD; \ | 23 | uint8_t VAR_MOVE_NOMOD, VAR_MOD; \ |
| 24 | for (VAR_B = ARG_BUF, ARG_C = 0; *VAR_B != '\0'; VAR_B++, ARG_C++) { \ | 24 | for (VAR_B = ARG_BUF, ARG_C = 0; *VAR_B != '\0'; VAR_B++, ARG_C++) { \ |
| @@ -26,8 +26,10 @@ STATIC cube_t frommoves(const char *); | |||
| 26 | VAR_B++; \ | 26 | VAR_B++; \ |
| 27 | if (*VAR_B == '\0' || ARG_C == ARG_MAX) \ | 27 | if (*VAR_B == '\0' || ARG_C == ARG_MAX) \ |
| 28 | break; \ | 28 | break; \ |
| 29 | if ((VAR_MOVE_NOMOD = readmove(*VAR_B)) == UINT8_ERROR) \ | 29 | if ((VAR_MOVE_NOMOD = readmove(*VAR_B)) == UINT8_ERROR) { \ |
| 30 | goto LABEL_ERROR; \ | 30 | LOG("Error: unknown move '%c'\n", *VAR_B); \ |
| 31 | return RET_ERROR; \ | ||
| 32 | } \ | ||
| 31 | if ((VAR_MOD = readmodifier(*(VAR_B+1))) != 0) \ | 33 | if ((VAR_MOD = readmodifier(*(VAR_B+1))) != 0) \ |
| 32 | VAR_B++; \ | 34 | VAR_B++; \ |
| 33 | ARG_MOVE = VAR_MOVE_NOMOD + VAR_MOD; \ | 35 | ARG_MOVE = VAR_MOVE_NOMOD + VAR_MOD; \ |
| @@ -124,7 +126,7 @@ move(cube_t c, uint8_t m) | |||
| 124 | case MOVE_B3: | 126 | case MOVE_B3: |
| 125 | return MOVE(B3, c); | 127 | return MOVE(B3, c); |
| 126 | default: | 128 | default: |
| 127 | LOG("move error, unknown move\n"); | 129 | LOG("move error: unknown move %" PRIu8 "\n", m); |
| 128 | return ZERO_CUBE; | 130 | return ZERO_CUBE; |
| 129 | } | 131 | } |
| 130 | } | 132 | } |
| @@ -171,7 +173,7 @@ premove(cube_t c, uint8_t m) | |||
| 171 | case MOVE_B3: | 173 | case MOVE_B3: |
| 172 | return PREMOVE(B, c); | 174 | return PREMOVE(B, c); |
| 173 | default: | 175 | default: |
| 174 | LOG("move error, unknown move\n"); | 176 | LOG("premove error: unknown move %" PRIu8 "\n", m); |
| 175 | return ZERO_CUBE; | 177 | return ZERO_CUBE; |
| 176 | } | 178 | } |
| 177 | } | 179 | } |
| @@ -222,15 +224,11 @@ readmoves(const char *buf, int max, uint8_t *ret) | |||
| 222 | uint8_t m; | 224 | uint8_t m; |
| 223 | int c; | 225 | int c; |
| 224 | 226 | ||
| 225 | FOREACH_READMOVE(buf, m, c, max, readmoves_error, | 227 | FOREACH_READMOVE(buf, m, c, max, -1, |
| 226 | ret[c] = m; | 228 | ret[c] = m; |
| 227 | ) | 229 | ) |
| 228 | 230 | ||
| 229 | return c; | 231 | return c; |
| 230 | |||
| 231 | readmoves_error: | ||
| 232 | LOG("readmoves error\n"); | ||
| 233 | return -1; | ||
| 234 | } | 232 | } |
| 235 | 233 | ||
| 236 | STATIC cube_t | 234 | STATIC cube_t |
| @@ -242,15 +240,11 @@ applymoves(cube_t cube, const char *buf) | |||
| 242 | DBG_ASSERT(isconsistent(cube), ZERO_CUBE, | 240 | DBG_ASSERT(isconsistent(cube), ZERO_CUBE, |
| 243 | "move error: inconsistent cube\n"); | 241 | "move error: inconsistent cube\n"); |
| 244 | 242 | ||
| 245 | FOREACH_READMOVE(buf, m, c, -1, applymoves_error, | 243 | FOREACH_READMOVE(buf, m, c, -1, ZERO_CUBE, |
| 246 | cube = move(cube, m); | 244 | cube = move(cube, m); |
| 247 | ) | 245 | ) |
| 248 | 246 | ||
| 249 | return cube; | 247 | return cube; |
| 250 | |||
| 251 | applymoves_error: | ||
| 252 | LOG("applymoves error\n"); | ||
| 253 | return ZERO_CUBE; | ||
| 254 | } | 248 | } |
| 255 | 249 | ||
| 256 | STATIC cube_t | 250 | STATIC cube_t |
diff --git a/src/core/transform.h b/src/core/transform.h index 83204d5..73636fe 100644 --- a/src/core/transform.h +++ b/src/core/transform.h | |||
| @@ -229,7 +229,7 @@ transform_corners(cube_t c, uint8_t t) | |||
| 229 | case TRANS_BLm: | 229 | case TRANS_BLm: |
| 230 | return TRANS_CORNERS_MIRRORED(BLm, c); | 230 | return TRANS_CORNERS_MIRRORED(BLm, c); |
| 231 | default: | 231 | default: |
| 232 | LOG("transform error, unknown transformation %" PRIu8 "\n", t); | 232 | LOG("transform error: unknown transformation %" PRIu8 "\n", t); |
| 233 | return ZERO_CUBE; | 233 | return ZERO_CUBE; |
| 234 | } | 234 | } |
| 235 | } | 235 | } |
| @@ -335,7 +335,6 @@ transform(cube_t c, uint8_t t) | |||
| 335 | case TRANS_BLm: | 335 | case TRANS_BLm: |
| 336 | return TRANS_MIRRORED(BLm, c); | 336 | return TRANS_MIRRORED(BLm, c); |
| 337 | default: | 337 | default: |
| 338 | LOG("transform error, unknown transformation %" PRIu8 "\n", t); | ||
| 339 | return ZERO_CUBE; | 338 | return ZERO_CUBE; |
| 340 | } | 339 | } |
| 341 | } | 340 | } |
| @@ -350,5 +349,8 @@ applytrans(cube_t cube, const char *buf) | |||
| 350 | 349 | ||
| 351 | t = readtrans(buf); | 350 | t = readtrans(buf); |
| 352 | 351 | ||
| 352 | if (t == UINT8_ERROR) | ||
| 353 | LOG("Unknown transformation '%s'\n", buf); | ||
| 354 | |||
| 353 | return transform(cube, t); | 355 | return transform(cube, t); |
| 354 | } | 356 | } |
diff --git a/src/nissy.c b/src/nissy.c index 4a4c0fd..1829d5c 100644 --- a/src/nissy.c +++ b/src/nissy.c | |||
| @@ -110,13 +110,19 @@ STATIC int64_t | |||
| 110 | write_result(cube_t cube, char result[static 22]) | 110 | write_result(cube_t cube, char result[static 22]) |
| 111 | { | 111 | { |
| 112 | if (!isconsistent(cube)) { | 112 | if (!isconsistent(cube)) { |
| 113 | LOG("Error: resulting cube is invalid\n"); | ||
| 113 | writecube("B32", ZERO_CUBE, result); | 114 | writecube("B32", ZERO_CUBE, result); |
| 114 | return 2; | 115 | return 8; |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 117 | writecube("B32", cube, result); | 118 | writecube("B32", cube, result); |
| 118 | 119 | ||
| 119 | return issolvable(cube) ? 0 : 1; | 120 | if (!issolvable(cube)) { |
| 121 | LOG("Warning: resulting cube is not solvable\n"); | ||
| 122 | return 9; | ||
| 123 | } | ||
| 124 | |||
| 125 | return 0; | ||
| 120 | } | 126 | } |
| 121 | 127 | ||
| 122 | int64_t | 128 | int64_t |
| @@ -129,7 +135,19 @@ nissy_compose( | |||
| 129 | cube_t c, p, res; | 135 | cube_t c, p, res; |
| 130 | 136 | ||
| 131 | c = readcube("B32", cube); | 137 | c = readcube("B32", cube); |
| 138 | |||
| 139 | if (!isconsistent(c)) { | ||
| 140 | LOG("Error in nissy_compose: given cube is invalid\n"); | ||
| 141 | return 1; | ||
| 142 | } | ||
| 143 | |||
| 132 | p = readcube("B32", permutation); | 144 | p = readcube("B32", permutation); |
| 145 | |||
| 146 | if (!isconsistent(p)) { | ||
| 147 | LOG("Error in nissy_compose: given permutation is invalid\n"); | ||
| 148 | return 2; | ||
| 149 | } | ||
| 150 | |||
| 133 | res = compose(c, p); | 151 | res = compose(c, p); |
| 134 | 152 | ||
| 135 | return write_result(res, result); | 153 | return write_result(res, result); |
| @@ -144,6 +162,12 @@ nissy_inverse( | |||
| 144 | cube_t c, res; | 162 | cube_t c, res; |
| 145 | 163 | ||
| 146 | c = readcube("B32", cube); | 164 | c = readcube("B32", cube); |
| 165 | |||
| 166 | if (iserror(c)) { | ||
| 167 | LOG("Error in nissy_inverse: given cube is invalid\n"); | ||
| 168 | return 1; | ||
| 169 | } | ||
| 170 | |||
| 147 | res = inverse(c); | 171 | res = inverse(c); |
| 148 | 172 | ||
| 149 | return write_result(res, result); | 173 | return write_result(res, result); |
| @@ -159,6 +183,12 @@ nissy_applymoves( | |||
| 159 | cube_t c, res; | 183 | cube_t c, res; |
| 160 | 184 | ||
| 161 | c = readcube("B32", cube); | 185 | c = readcube("B32", cube); |
| 186 | |||
| 187 | if (!isconsistent(c)) { | ||
| 188 | LOG("Error in nissy_applymoves: given cube is invalid\n"); | ||
| 189 | return 1; | ||
| 190 | } | ||
| 191 | |||
| 162 | res = applymoves(c, moves); | 192 | res = applymoves(c, moves); |
| 163 | 193 | ||
| 164 | return write_result(res, result); | 194 | return write_result(res, result); |
| @@ -174,6 +204,12 @@ nissy_applytrans( | |||
| 174 | cube_t c, res; | 204 | cube_t c, res; |
| 175 | 205 | ||
| 176 | c = readcube("B32", cube); | 206 | c = readcube("B32", cube); |
| 207 | |||
| 208 | if (!isconsistent(c)) { | ||
| 209 | LOG("Error in nissy_applytrans: given cube is invalid\n"); | ||
| 210 | return 1; | ||
| 211 | } | ||
| 212 | |||
| 177 | res = applytrans(c, transformation); | 213 | res = applytrans(c, transformation); |
| 178 | 214 | ||
| 179 | return write_result(res, result); | 215 | return write_result(res, result); |
| @@ -189,6 +225,11 @@ nissy_frommoves( | |||
| 189 | 225 | ||
| 190 | res = applymoves(SOLVED_CUBE, moves); | 226 | res = applymoves(SOLVED_CUBE, moves); |
| 191 | 227 | ||
| 228 | if (!isconsistent(res)) { | ||
| 229 | /* Moves must be invalid */ | ||
| 230 | return 1; | ||
| 231 | } | ||
| 232 | |||
| 192 | return write_result(res, result); | 233 | return write_result(res, result); |
| 193 | } | 234 | } |
| 194 | 235 | ||
| @@ -200,12 +241,20 @@ nissy_convert( | |||
| 200 | char *result | 241 | char *result |
| 201 | ) | 242 | ) |
| 202 | { | 243 | { |
| 244 | int ret; | ||
| 203 | cube_t c; | 245 | cube_t c; |
| 204 | 246 | ||
| 205 | c = readcube(format_in, cube_string); | 247 | c = readcube(format_in, cube_string); |
| 206 | writecube(format_out, c, result); | ||
| 207 | 248 | ||
| 208 | return isconsistent(c) ? 0 : 2; | 249 | if (iserror(c)) |
| 250 | return 1; | ||
| 251 | |||
| 252 | ret = writecube(format_out, c, result); | ||
| 253 | |||
| 254 | if (ret != 0) | ||
| 255 | return 2; | ||
| 256 | |||
| 257 | return isconsistent(c) ? 0 : 3; | ||
| 209 | } | 258 | } |
| 210 | 259 | ||
| 211 | int64_t | 260 | int64_t |
| @@ -387,8 +436,10 @@ nissy_solve( | |||
| 387 | return -1; | 436 | return -1; |
| 388 | } else { | 437 | } else { |
| 389 | return THREADS > 1 ? | 438 | return THREADS > 1 ? |
| 390 | solve_h48_multithread(c, minmoves, maxmoves, maxsolutions, data, solutions) : | 439 | solve_h48_multithread(c, minmoves, |
| 391 | solve_h48(c, minmoves, maxmoves, maxsolutions, data, solutions); | 440 | maxmoves, maxsolutions, data, solutions) : |
| 441 | solve_h48(c, minmoves, | ||
| 442 | maxmoves, maxsolutions, data, solutions); | ||
| 392 | } | 443 | } |
| 393 | } else if (!strcmp(solver, "simple")) { | 444 | } else if (!strcmp(solver, "simple")) { |
| 394 | return solve_simple( | 445 | return solve_simple( |
diff --git a/src/nissy.h b/src/nissy.h index 1fc1776..c78fb50 100644 --- a/src/nissy.h +++ b/src/nissy.h | |||
| @@ -1,10 +1,17 @@ | |||
| 1 | /* | 1 | /* |
| 2 | If you include this file, you should also include the following: | 2 | This is libnissy (temporarily also known as h48), a Rubik's cube library. |
| 3 | 3 | ||
| 4 | inttypes, stdarg, stdbool, string | 4 | If you include this file, you should also use the following includes: |
| 5 | 5 | ||
| 6 | All the functions below return 0 in case of success and a positive | 6 | #include <inttypes> |
| 7 | number in case of error, unless otherwise specified. | 7 | #include <stdarg> |
| 8 | #include <stdbool> | ||
| 9 | #include <string> | ||
| 10 | |||
| 11 | All the functions below return 0 in case of success and a positive number | ||
| 12 | in case of error, unless otherwise specified. Errors are checked in code | ||
| 13 | order: for example if error code 1 is returned then it could that also | ||
| 14 | an error with code 2 or higher occurred. | ||
| 8 | 15 | ||
| 9 | Arguments of type char [static 22] denote a cube in B32 format. | 16 | Arguments of type char [static 22] denote a cube in B32 format. |
| 10 | Other available formats are H48 and SRC. See README.md for more info on | 17 | Other available formats are H48 and SRC. See README.md for more info on |
| @@ -18,40 +25,85 @@ A transformation must be given in the format | |||
| 18 | for example 'rotation UF' or 'mirrored BL'. | 25 | for example 'rotation UF' or 'mirrored BL'. |
| 19 | */ | 26 | */ |
| 20 | 27 | ||
| 21 | /* Apply the secod argument as a permutation on the first argument */ | 28 | /* |
| 29 | Apply the secod argument as a permutation on the first argument. | ||
| 30 | |||
| 31 | Return values: | ||
| 32 | 0 Valid result | ||
| 33 | 1 The given cube is invalid | ||
| 34 | 2 The given permutation is invalid | ||
| 35 | 9 The resulting cube is not solvable | ||
| 36 | */ | ||
| 22 | int64_t nissy_compose( | 37 | int64_t nissy_compose( |
| 23 | const char cube[static 22], | 38 | const char cube[static 22], |
| 24 | const char permutation[static 22], | 39 | const char permutation[static 22], |
| 25 | char result[static 22] | 40 | char result[static 22] |
| 26 | ); | 41 | ); |
| 27 | 42 | ||
| 28 | /* Compute the inverse of the given cube */ | 43 | /* |
| 44 | Compute the inverse of the given cube. | ||
| 45 | |||
| 46 | Return values: | ||
| 47 | 0 Valid result | ||
| 48 | 1 The given cube is invalid | ||
| 49 | 9 The resulting cube is not solvable | ||
| 50 | */ | ||
| 29 | int64_t nissy_inverse( | 51 | int64_t nissy_inverse( |
| 30 | const char cube[static 22], | 52 | const char cube[static 22], |
| 31 | char result[static 22] | 53 | char result[static 22] |
| 32 | ); | 54 | ); |
| 33 | 55 | ||
| 34 | /* Apply the given sequence of moves on the given cube */ | 56 | /* |
| 57 | Apply the given sequence of moves on the given cube. | ||
| 58 | |||
| 59 | Return values: | ||
| 60 | 0 Valid result | ||
| 61 | 1 The given cube is invalid | ||
| 62 | 8 The given moves are invalid | ||
| 63 | 9 The resulting cube is not solvable | ||
| 64 | */ | ||
| 35 | int64_t nissy_applymoves( | 65 | int64_t nissy_applymoves( |
| 36 | const char cube[static 22], | 66 | const char cube[static 22], |
| 37 | const char *moves, | 67 | const char *moves, |
| 38 | char result[static 22] | 68 | char result[static 22] |
| 39 | ); | 69 | ); |
| 40 | 70 | ||
| 41 | /* Apply the single given transformation to the given cube */ | 71 | /* |
| 72 | Apply the single given transformation to the given cube. | ||
| 73 | |||
| 74 | Return values: | ||
| 75 | 0 Valid result | ||
| 76 | 1 The given cube is invalid | ||
| 77 | 8 The given transformation is invalid | ||
| 78 | 9 The resulting cube is not solvable | ||
| 79 | */ | ||
| 42 | int64_t nissy_applytrans( | 80 | int64_t nissy_applytrans( |
| 43 | const char cube[static 22], | 81 | const char cube[static 22], |
| 44 | const char *transformation, | 82 | const char *transformation, |
| 45 | char result[static 22] | 83 | char result[static 22] |
| 46 | ); | 84 | ); |
| 47 | 85 | ||
| 48 | /* Return the cube obtained by applying the given moves to the solved cube */ | 86 | /* |
| 87 | Apply the given moves to the solved cube. | ||
| 88 | |||
| 89 | Return values: | ||
| 90 | 0 Valid result | ||
| 91 | 1 The given moves are invalid | ||
| 92 | */ | ||
| 49 | int64_t nissy_frommoves( | 93 | int64_t nissy_frommoves( |
| 50 | const char *moves, | 94 | const char *moves, |
| 51 | char result[static 22] | 95 | char result[static 22] |
| 52 | ); | 96 | ); |
| 53 | 97 | ||
| 54 | /* Convert the given cube between the two given formats */ | 98 | /* |
| 99 | Convert the given cube between the two given formats. | ||
| 100 | |||
| 101 | Return values: | ||
| 102 | 0 Valid result | ||
| 103 | 1 The given cube or format_in is invalid | ||
| 104 | 2 The resulting cube or format_out is invalid | ||
| 105 | 3 The resulting cube is inconsistent | ||
| 106 | */ | ||
| 55 | int64_t nissy_convert( | 107 | int64_t nissy_convert( |
| 56 | const char *format_in, | 108 | const char *format_in, |
| 57 | const char *format_out, | 109 | const char *format_out, |
| @@ -70,40 +122,48 @@ int64_t nissy_getcube( | |||
| 70 | ); | 122 | ); |
| 71 | 123 | ||
| 72 | /* | 124 | /* |
| 73 | Returns the size of the data generated by nissy_gendata, when called with | 125 | Compute the size of the data generated by nissy_gendata, when called with |
| 74 | the same parameters, or -1 in case of error. The returned value can be | 126 | the same parameters, or -1 in case of error. |
| 75 | slightly larger than the actual table size. | 127 | |
| 128 | Return values: | ||
| 129 | -1 Error | ||
| 130 | >=0 The size of the table, in bytes | ||
| 76 | */ | 131 | */ |
| 77 | int64_t nissy_datasize( | 132 | int64_t nissy_datasize( |
| 78 | const char *solver | 133 | const char *solver |
| 79 | ); | 134 | ); |
| 80 | 135 | ||
| 81 | /* Returns the number of bytes written, or -1 in case of error */ | 136 | /* |
| 137 | Compute the data for the given solver and store it in generated_data. | ||
| 138 | |||
| 139 | Return values: | ||
| 140 | -1 Error | ||
| 141 | >=0 The size of the table, in bytes | ||
| 142 | */ | ||
| 82 | int64_t nissy_gendata( | 143 | int64_t nissy_gendata( |
| 83 | const char *solver, | 144 | const char *solver, |
| 84 | void *generated_data | 145 | void *generated_data |
| 85 | ); | 146 | ); |
| 86 | 147 | ||
| 87 | /* Temporarily added to test h48 intermediate tables */ | 148 | /* |
| 88 | int64_t nissy_derivedata( | 149 | Print information on a data table via the provided callback writer. |
| 89 | const char *options, | ||
| 90 | const void *fulltable, | ||
| 91 | void *generated_data | ||
| 92 | ); | ||
| 93 | |||
| 94 | /* Returns 0 on positive check, 1 on error */ | ||
| 95 | int64_t nissy_checkdata( | ||
| 96 | const char *solver, | ||
| 97 | const void *data | ||
| 98 | ); | ||
| 99 | 150 | ||
| 100 | /* Print information on a data table via the provided callback writer */ | 151 | Return values: |
| 152 | 0 No error | ||
| 153 | 1 The given data could not be read correctly | ||
| 154 | */ | ||
| 101 | int64_t nissy_datainfo( | 155 | int64_t nissy_datainfo( |
| 102 | const void *table, | 156 | const void *table, |
| 103 | void (*write)(const char *, ...) | 157 | void (*write)(const char *, ...) |
| 104 | ); | 158 | ); |
| 105 | 159 | ||
| 106 | /* Returns the number of solutions found, or -1 in case of error */ | 160 | /* |
| 161 | Solve the given cube using the given solver and options | ||
| 162 | |||
| 163 | Return values: | ||
| 164 | -1 Error | ||
| 165 | >=0 The number of solutions found | ||
| 166 | */ | ||
| 107 | int64_t nissy_solve( | 167 | int64_t nissy_solve( |
| 108 | const char cube[static 22], | 168 | const char cube[static 22], |
| 109 | const char *solver, | 169 | const char *solver, |
| @@ -116,5 +176,7 @@ int64_t nissy_solve( | |||
| 116 | char *solutions | 176 | char *solutions |
| 117 | ); | 177 | ); |
| 118 | 178 | ||
| 119 | /* Set a global logger function used by this library. */ | 179 | /* |
| 180 | Set a global logger function used by this library. | ||
| 181 | */ | ||
| 120 | void nissy_setlogger(void (*logger_function)(const char *, ...)); | 182 | void nissy_setlogger(void (*logger_function)(const char *, ...)); |
diff --git a/tools/nissy_extra.h b/tools/nissy_extra.h index 53c3df7..cc7b088 100644 --- a/tools/nissy_extra.h +++ b/tools/nissy_extra.h | |||
| @@ -10,3 +10,4 @@ for testing purposes only. | |||
| 10 | 10 | ||
| 11 | size_t gendata_h48_derive(uint8_t, const void *, void *); | 11 | size_t gendata_h48_derive(uint8_t, const void *, void *); |
| 12 | int parse_h48_solver(const char *, uint8_t [static 1], uint8_t [static 1]); | 12 | int parse_h48_solver(const char *, uint8_t [static 1], uint8_t [static 1]); |
| 13 | int64_t nissy_derivedata(const char *, const void *, void *); | ||
