diff options
Diffstat (limited to 'cube.c')
| -rw-r--r-- | cube.c | 643 |
1 files changed, 299 insertions, 344 deletions
| @@ -43,11 +43,265 @@ _static void write_H48(cube_t, char *); | |||
| 43 | _static void write_LST(cube_t, char *); | 43 | _static void write_LST(cube_t, char *); |
| 44 | _static uint8_t readmove(char); | 44 | _static uint8_t readmove(char); |
| 45 | _static uint8_t readmodifier(char); | 45 | _static uint8_t readmodifier(char); |
| 46 | _static uint8_t readtrans(char *); | 46 | |
| 47 | _static int writemoves(uint8_t *, int, char *); | 47 | _static uint8_t |
| 48 | _static void writetrans(uint8_t, char *); | 48 | readco(char *str) |
| 49 | _static cube_t move(cube_t, move_t); | 49 | { |
| 50 | _static cube_t transform(cube_t, trans_t); | 50 | if (*str == '0') |
| 51 | return 0; | ||
| 52 | if (*str == '1') | ||
| 53 | return _ctwist_cw; | ||
| 54 | if (*str == '2') | ||
| 55 | return _ctwist_ccw; | ||
| 56 | |||
| 57 | DBG_LOG("Error reading CO\n"); | ||
| 58 | return _error; | ||
| 59 | } | ||
| 60 | |||
| 61 | _static uint8_t | ||
| 62 | readcp(char *str) | ||
| 63 | { | ||
| 64 | uint8_t c; | ||
| 65 | |||
| 66 | for (c = 0; c < 8; c++) | ||
| 67 | if (!strncmp(str, cornerstr[c], 3) || | ||
| 68 | !strncmp(str, cornerstralt[c], 3)) | ||
| 69 | return c; | ||
| 70 | |||
| 71 | DBG_LOG("Error reading CP\n"); | ||
| 72 | return _error; | ||
| 73 | } | ||
| 74 | |||
| 75 | _static uint8_t | ||
| 76 | readeo(char *str) | ||
| 77 | { | ||
| 78 | if (*str == '0') | ||
| 79 | return 0; | ||
| 80 | if (*str == '1') | ||
| 81 | return _eflip; | ||
| 82 | |||
| 83 | DBG_LOG("Error reading EO\n"); | ||
| 84 | return _error; | ||
| 85 | } | ||
| 86 | |||
| 87 | _static uint8_t | ||
| 88 | readep(char *str) | ||
| 89 | { | ||
| 90 | uint8_t e; | ||
| 91 | |||
| 92 | for (e = 0; e < 12; e++) | ||
| 93 | if (!strncmp(str, edgestr[e], 2)) | ||
| 94 | return e; | ||
| 95 | |||
| 96 | DBG_LOG("Error reading EP\n"); | ||
| 97 | return _error; | ||
| 98 | } | ||
| 99 | |||
| 100 | _static cube_t | ||
| 101 | read_H48(char *buf) | ||
| 102 | { | ||
| 103 | int i; | ||
| 104 | uint8_t piece, orient; | ||
| 105 | cube_t ret = {0}; | ||
| 106 | char *b; | ||
| 107 | |||
| 108 | b = buf; | ||
| 109 | |||
| 110 | for (i = 0; i < 12; i++) { | ||
| 111 | while (*b == ' ' || *b == '\t' || *b == '\n') | ||
| 112 | b++; | ||
| 113 | if ((piece = readep(b)) == _error) | ||
| 114 | return zero; | ||
| 115 | b += 2; | ||
| 116 | if ((orient = readeo(b)) == _error) | ||
| 117 | return zero; | ||
| 118 | b++; | ||
| 119 | ret.edge[i] = piece | orient; | ||
| 120 | } | ||
| 121 | for (i = 0; i < 8; i++) { | ||
| 122 | while (*b == ' ' || *b == '\t' || *b == '\n') | ||
| 123 | b++; | ||
| 124 | if ((piece = readcp(b)) == _error) | ||
| 125 | return zero; | ||
| 126 | b += 3; | ||
| 127 | if ((orient = readco(b)) == _error) | ||
| 128 | return zero; | ||
| 129 | b++; | ||
| 130 | ret.corner[i] = piece | orient; | ||
| 131 | } | ||
| 132 | |||
| 133 | return ret; | ||
| 134 | } | ||
| 135 | |||
| 136 | _static uint8_t | ||
| 137 | readpiece_LST(char **b) | ||
| 138 | { | ||
| 139 | uint8_t ret; | ||
| 140 | bool read; | ||
| 141 | |||
| 142 | while (**b == ',' || **b == ' ' || **b == '\t' || **b == '\n') | ||
| 143 | (*b)++; | ||
| 144 | |||
| 145 | for (ret = 0, read = false; **b >= '0' && **b <= '9'; (*b)++) { | ||
| 146 | read = true; | ||
| 147 | ret = ret * 10 + (**b) - '0'; | ||
| 148 | } | ||
| 149 | |||
| 150 | return read ? ret : _error; | ||
| 151 | } | ||
| 152 | |||
| 153 | _static cube_t | ||
| 154 | read_LST(char *buf) | ||
| 155 | { | ||
| 156 | int i; | ||
| 157 | cube_t ret = {0}; | ||
| 158 | |||
| 159 | for (i = 0; i < 8; i++) | ||
| 160 | ret.corner[i] = readpiece_LST(&buf); | ||
| 161 | |||
| 162 | for (i = 0; i < 12; i++) | ||
| 163 | ret.edge[i] = readpiece_LST(&buf); | ||
| 164 | |||
| 165 | return ret; | ||
| 166 | } | ||
| 167 | |||
| 168 | _static int | ||
| 169 | writepiece_LST(uint8_t piece, char *buf) | ||
| 170 | { | ||
| 171 | char digits[3]; | ||
| 172 | int i, len = 0; | ||
| 173 | |||
| 174 | while (piece != 0) { | ||
| 175 | digits[len++] = (piece % 10) + '0'; | ||
| 176 | piece /= 10; | ||
| 177 | } | ||
| 178 | |||
| 179 | if (len == 0) | ||
| 180 | digits[len++] = '0'; | ||
| 181 | |||
| 182 | for (i = 0; i < len; i++) | ||
| 183 | buf[i] = digits[len-i-1]; | ||
| 184 | |||
| 185 | buf[len] = ','; | ||
| 186 | buf[len+1] = ' '; | ||
| 187 | |||
| 188 | return len+2; | ||
| 189 | } | ||
| 190 | |||
| 191 | _static void | ||
| 192 | write_H48(cube_t cube, char *buf) | ||
| 193 | { | ||
| 194 | uint8_t piece, perm, orient; | ||
| 195 | int i; | ||
| 196 | |||
| 197 | for (i = 0; i < 12; i++) { | ||
| 198 | piece = cube.edge[i]; | ||
| 199 | perm = piece & _pbits; | ||
| 200 | orient = (piece & _eobit) >> _eoshift; | ||
| 201 | buf[4*i ] = edgestr[perm][0]; | ||
| 202 | buf[4*i + 1] = edgestr[perm][1]; | ||
| 203 | buf[4*i + 2] = orient + '0'; | ||
| 204 | buf[4*i + 3] = ' '; | ||
| 205 | } | ||
| 206 | for (i = 0; i < 8; i++) { | ||
| 207 | piece = cube.corner[i]; | ||
| 208 | perm = piece & _pbits; | ||
| 209 | orient = (piece & _cobits) >> _coshift; | ||
| 210 | buf[48 + 5*i ] = cornerstr[perm][0]; | ||
| 211 | buf[48 + 5*i + 1] = cornerstr[perm][1]; | ||
| 212 | buf[48 + 5*i + 2] = cornerstr[perm][2]; | ||
| 213 | buf[48 + 5*i + 3] = orient + '0'; | ||
| 214 | buf[48 + 5*i + 4] = ' '; | ||
| 215 | } | ||
| 216 | |||
| 217 | buf[48+39] = '\0'; | ||
| 218 | } | ||
| 219 | |||
| 220 | _static void | ||
| 221 | write_LST(cube_t cube, char *buf) | ||
| 222 | { | ||
| 223 | int i, ptr; | ||
| 224 | uint8_t piece; | ||
| 225 | |||
| 226 | ptr = 0; | ||
| 227 | |||
| 228 | for (i = 0; i < 8; i++) { | ||
| 229 | piece = cube.corner[i]; | ||
| 230 | ptr += writepiece_LST(piece, buf + ptr); | ||
| 231 | } | ||
| 232 | |||
| 233 | for (i = 0; i < 12; i++) { | ||
| 234 | piece = cube.edge[i]; | ||
| 235 | ptr += writepiece_LST(piece, buf + ptr); | ||
| 236 | } | ||
| 237 | |||
| 238 | *(buf+ptr-2) = 0; | ||
| 239 | } | ||
| 240 | |||
| 241 | _static uint8_t | ||
| 242 | readmove(char c) | ||
| 243 | { | ||
| 244 | switch (c) { | ||
| 245 | case 'U': | ||
| 246 | return U; | ||
| 247 | case 'D': | ||
| 248 | return D; | ||
| 249 | case 'R': | ||
| 250 | return R; | ||
| 251 | case 'L': | ||
| 252 | return L; | ||
| 253 | case 'F': | ||
| 254 | return F; | ||
| 255 | case 'B': | ||
| 256 | return B; | ||
| 257 | default: | ||
| 258 | return _error; | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | _static uint8_t | ||
| 263 | readmodifier(char c) | ||
| 264 | { | ||
| 265 | switch (c) { | ||
| 266 | case '1': /* Fallthrough */ | ||
| 267 | case '2': /* Fallthrough */ | ||
| 268 | case '3': | ||
| 269 | return c - '0' - 1; | ||
| 270 | case '\'': | ||
| 271 | return 2; | ||
| 272 | default: | ||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | } | ||
| 276 | |||
| 277 | _static_inline cube_t | ||
| 278 | invertco(cube_t c) | ||
| 279 | { | ||
| 280 | uint8_t i, piece, orien; | ||
| 281 | cube_t ret; | ||
| 282 | |||
| 283 | ret = c; | ||
| 284 | for (i = 0; i < 8; i++) { | ||
| 285 | piece = c.corner[i]; | ||
| 286 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; | ||
| 287 | ret.corner[i] = (piece & _pbits) | orien; | ||
| 288 | } | ||
| 289 | |||
| 290 | return ret; | ||
| 291 | } | ||
| 292 | |||
| 293 | _static int | ||
| 294 | permsign(uint8_t *a, int n) | ||
| 295 | { | ||
| 296 | int i, j; | ||
| 297 | uint8_t ret = 0; | ||
| 298 | |||
| 299 | for (i = 0; i < n; i++) | ||
| 300 | for (j = i+1; j < n; j++) | ||
| 301 | ret += a[i] > a[j] ? 1 : 0; | ||
| 302 | |||
| 303 | return ret % 2; | ||
| 304 | } | ||
| 51 | 305 | ||
| 52 | cube_t | 306 | cube_t |
| 53 | cube_new(void) | 307 | cube_new(void) |
| @@ -250,51 +504,22 @@ cube_inverse(cube_t cube) | |||
| 250 | } | 504 | } |
| 251 | 505 | ||
| 252 | cube_t | 506 | cube_t |
| 253 | applymoves(cube_t cube, char *buf) | 507 | cube_move(cube_t c, move_t m) |
| 254 | { | 508 | { |
| 255 | cube_t ret; | 509 | return cube_compose(c, move_table[m]); |
| 256 | uint8_t r, m; | ||
| 257 | char *b; | ||
| 258 | |||
| 259 | DBG_ASSERT(cube_consistent(cube), zero, | ||
| 260 | "move error: inconsistent cube\n"); | ||
| 261 | |||
| 262 | ret = cube_clone(cube); | ||
| 263 | |||
| 264 | for (b = buf; *b != '\0'; b++) { | ||
| 265 | while (*b == ' ' || *b == '\t' || *b == '\n') | ||
| 266 | b++; | ||
| 267 | if (*b == '\0') | ||
| 268 | goto applymoves_finish; | ||
| 269 | if ((r = readmove(*b)) == _error) | ||
| 270 | goto applymoves_error; | ||
| 271 | if ((m = readmodifier(*(b+1))) != 0) | ||
| 272 | b++; | ||
| 273 | ret = move(ret, r + m); | ||
| 274 | } | ||
| 275 | |||
| 276 | applymoves_finish: | ||
| 277 | return ret; | ||
| 278 | |||
| 279 | applymoves_error: | ||
| 280 | DBG_LOG("applymoves error\n"); | ||
| 281 | return zero; | ||
| 282 | } | 510 | } |
| 283 | 511 | ||
| 284 | cube_t | 512 | cube_t |
| 285 | applytrans(cube_t cube, char *buf) | 513 | cube_transform(cube_t c, trans_t t) |
| 286 | { | 514 | { |
| 287 | cube_t ret; | 515 | cube_t tcube, tinv; |
| 288 | uint8_t t; | ||
| 289 | |||
| 290 | DBG_ASSERT(cube_consistent(cube), zero, | ||
| 291 | "transformation error: inconsistent cube\n"); | ||
| 292 | 516 | ||
| 293 | t = readtrans(buf); | 517 | tcube = trans_table[t][NORMAL]; |
| 294 | ret = cube_clone(cube); | 518 | tinv = trans_table[t][INVERSE]; |
| 295 | ret = transform(ret, t); | ||
| 296 | 519 | ||
| 297 | return cube_clone(ret); | 520 | return t < 24 ? |
| 521 | cube_compose(cube_compose(tcube, c), tinv) : | ||
| 522 | invertco(cube_compose(cube_compose(tcube, c), tinv)); | ||
| 298 | } | 523 | } |
| 299 | 524 | ||
| 300 | int64_t | 525 | int64_t |
| @@ -368,335 +593,65 @@ write_error: | |||
| 368 | buf[len+1] = '\0'; | 593 | buf[len+1] = '\0'; |
| 369 | } | 594 | } |
| 370 | 595 | ||
| 371 | _static int | 596 | int |
| 372 | permsign(uint8_t *a, int n) | 597 | cube_readmoves(char *buf, move_t *ret) |
| 373 | { | ||
| 374 | int i, j; | ||
| 375 | uint8_t ret = 0; | ||
| 376 | |||
| 377 | for (i = 0; i < n; i++) | ||
| 378 | for (j = i+1; j < n; j++) | ||
| 379 | ret += a[i] > a[j] ? 1 : 0; | ||
| 380 | |||
| 381 | return ret % 2; | ||
| 382 | } | ||
| 383 | |||
| 384 | _static uint8_t | ||
| 385 | readco(char *str) | ||
| 386 | { | ||
| 387 | if (*str == '0') | ||
| 388 | return 0; | ||
| 389 | if (*str == '1') | ||
| 390 | return _ctwist_cw; | ||
| 391 | if (*str == '2') | ||
| 392 | return _ctwist_ccw; | ||
| 393 | |||
| 394 | DBG_LOG("Error reading CO\n"); | ||
| 395 | return _error; | ||
| 396 | } | ||
| 397 | |||
| 398 | _static uint8_t | ||
| 399 | readcp(char *str) | ||
| 400 | { | ||
| 401 | uint8_t c; | ||
| 402 | |||
| 403 | for (c = 0; c < 8; c++) | ||
| 404 | if (!strncmp(str, cornerstr[c], 3) || | ||
| 405 | !strncmp(str, cornerstralt[c], 3)) | ||
| 406 | return c; | ||
| 407 | |||
| 408 | DBG_LOG("Error reading CP\n"); | ||
| 409 | return _error; | ||
| 410 | } | ||
| 411 | |||
| 412 | _static uint8_t | ||
| 413 | readeo(char *str) | ||
| 414 | { | ||
| 415 | if (*str == '0') | ||
| 416 | return 0; | ||
| 417 | if (*str == '1') | ||
| 418 | return _eflip; | ||
| 419 | |||
| 420 | DBG_LOG("Error reading EO\n"); | ||
| 421 | return _error; | ||
| 422 | } | ||
| 423 | |||
| 424 | _static uint8_t | ||
| 425 | readep(char *str) | ||
| 426 | { | ||
| 427 | uint8_t e; | ||
| 428 | |||
| 429 | for (e = 0; e < 12; e++) | ||
| 430 | if (!strncmp(str, edgestr[e], 2)) | ||
| 431 | return e; | ||
| 432 | |||
| 433 | DBG_LOG("Error reading EP\n"); | ||
| 434 | return _error; | ||
| 435 | } | ||
| 436 | |||
| 437 | _static cube_t | ||
| 438 | read_H48(char *buf) | ||
| 439 | { | 598 | { |
| 440 | int i; | 599 | int n; |
| 441 | uint8_t piece, orient; | 600 | move_t r, m; |
| 442 | cube_t ret = {0}; | ||
| 443 | char *b; | 601 | char *b; |
| 444 | |||
| 445 | b = buf; | ||
| 446 | 602 | ||
| 447 | for (i = 0; i < 12; i++) { | 603 | for (n = 0, b = buf; *b != '\0'; b++) { |
| 448 | while (*b == ' ' || *b == '\t' || *b == '\n') | 604 | while (*b == ' ' || *b == '\t' || *b == '\n') |
| 449 | b++; | 605 | b++; |
| 450 | if ((piece = readep(b)) == _error) | 606 | if (*b == '\0') |
| 451 | return zero; | 607 | goto applymoves_finish; |
| 452 | b += 2; | 608 | if ((r = readmove(*b)) == _error) |
| 453 | if ((orient = readeo(b)) == _error) | 609 | goto applymoves_error; |
| 454 | return zero; | 610 | if ((m = readmodifier(*(b+1))) != 0) |
| 455 | b++; | ||
| 456 | ret.edge[i] = piece | orient; | ||
| 457 | } | ||
| 458 | for (i = 0; i < 8; i++) { | ||
| 459 | while (*b == ' ' || *b == '\t' || *b == '\n') | ||
| 460 | b++; | 611 | b++; |
| 461 | if ((piece = readcp(b)) == _error) | 612 | ret[n++] = m + r; |
| 462 | return zero; | ||
| 463 | b += 3; | ||
| 464 | if ((orient = readco(b)) == _error) | ||
| 465 | return zero; | ||
| 466 | b++; | ||
| 467 | ret.corner[i] = piece | orient; | ||
| 468 | } | ||
| 469 | |||
| 470 | return ret; | ||
| 471 | } | ||
| 472 | |||
| 473 | _static uint8_t | ||
| 474 | readpiece_LST(char **b) | ||
| 475 | { | ||
| 476 | uint8_t ret; | ||
| 477 | bool read; | ||
| 478 | |||
| 479 | while (**b == ',' || **b == ' ' || **b == '\t' || **b == '\n') | ||
| 480 | (*b)++; | ||
| 481 | |||
| 482 | for (ret = 0, read = false; **b >= '0' && **b <= '9'; (*b)++) { | ||
| 483 | read = true; | ||
| 484 | ret = ret * 10 + (**b) - '0'; | ||
| 485 | } | ||
| 486 | |||
| 487 | return read ? ret : _error; | ||
| 488 | } | ||
| 489 | |||
| 490 | _static cube_t | ||
| 491 | read_LST(char *buf) | ||
| 492 | { | ||
| 493 | int i; | ||
| 494 | cube_t ret = {0}; | ||
| 495 | |||
| 496 | for (i = 0; i < 8; i++) | ||
| 497 | ret.corner[i] = readpiece_LST(&buf); | ||
| 498 | |||
| 499 | for (i = 0; i < 12; i++) | ||
| 500 | ret.edge[i] = readpiece_LST(&buf); | ||
| 501 | |||
| 502 | return ret; | ||
| 503 | } | ||
| 504 | |||
| 505 | _static int | ||
| 506 | writepiece_LST(uint8_t piece, char *buf) | ||
| 507 | { | ||
| 508 | char digits[3]; | ||
| 509 | int i, len = 0; | ||
| 510 | |||
| 511 | while (piece != 0) { | ||
| 512 | digits[len++] = (piece % 10) + '0'; | ||
| 513 | piece /= 10; | ||
| 514 | } | ||
| 515 | |||
| 516 | if (len == 0) | ||
| 517 | digits[len++] = '0'; | ||
| 518 | |||
| 519 | for (i = 0; i < len; i++) | ||
| 520 | buf[i] = digits[len-i-1]; | ||
| 521 | |||
| 522 | buf[len] = ','; | ||
| 523 | buf[len+1] = ' '; | ||
| 524 | |||
| 525 | return len+2; | ||
| 526 | } | ||
| 527 | |||
| 528 | _static void | ||
| 529 | write_H48(cube_t cube, char *buf) | ||
| 530 | { | ||
| 531 | uint8_t piece, perm, orient; | ||
| 532 | int i; | ||
| 533 | |||
| 534 | for (i = 0; i < 12; i++) { | ||
| 535 | piece = cube.edge[i]; | ||
| 536 | perm = piece & _pbits; | ||
| 537 | orient = (piece & _eobit) >> _eoshift; | ||
| 538 | buf[4*i ] = edgestr[perm][0]; | ||
| 539 | buf[4*i + 1] = edgestr[perm][1]; | ||
| 540 | buf[4*i + 2] = orient + '0'; | ||
| 541 | buf[4*i + 3] = ' '; | ||
| 542 | } | ||
| 543 | for (i = 0; i < 8; i++) { | ||
| 544 | piece = cube.corner[i]; | ||
| 545 | perm = piece & _pbits; | ||
| 546 | orient = (piece & _cobits) >> _coshift; | ||
| 547 | buf[48 + 5*i ] = cornerstr[perm][0]; | ||
| 548 | buf[48 + 5*i + 1] = cornerstr[perm][1]; | ||
| 549 | buf[48 + 5*i + 2] = cornerstr[perm][2]; | ||
| 550 | buf[48 + 5*i + 3] = orient + '0'; | ||
| 551 | buf[48 + 5*i + 4] = ' '; | ||
| 552 | } | ||
| 553 | |||
| 554 | buf[48+39] = '\0'; | ||
| 555 | } | ||
| 556 | |||
| 557 | _static void | ||
| 558 | write_LST(cube_t cube, char *buf) | ||
| 559 | { | ||
| 560 | int i, ptr; | ||
| 561 | uint8_t piece; | ||
| 562 | |||
| 563 | ptr = 0; | ||
| 564 | |||
| 565 | for (i = 0; i < 8; i++) { | ||
| 566 | piece = cube.corner[i]; | ||
| 567 | ptr += writepiece_LST(piece, buf + ptr); | ||
| 568 | } | 613 | } |
| 569 | 614 | ||
| 570 | for (i = 0; i < 12; i++) { | 615 | applymoves_finish: |
| 571 | piece = cube.edge[i]; | 616 | return n; |
| 572 | ptr += writepiece_LST(piece, buf + ptr); | ||
| 573 | } | ||
| 574 | |||
| 575 | *(buf+ptr-2) = 0; | ||
| 576 | } | ||
| 577 | |||
| 578 | _static uint8_t | ||
| 579 | readmove(char c) | ||
| 580 | { | ||
| 581 | switch (c) { | ||
| 582 | case 'U': | ||
| 583 | return U; | ||
| 584 | case 'D': | ||
| 585 | return D; | ||
| 586 | case 'R': | ||
| 587 | return R; | ||
| 588 | case 'L': | ||
| 589 | return L; | ||
| 590 | case 'F': | ||
| 591 | return F; | ||
| 592 | case 'B': | ||
| 593 | return B; | ||
| 594 | default: | ||
| 595 | return _error; | ||
| 596 | } | ||
| 597 | } | ||
| 598 | 617 | ||
| 599 | _static uint8_t | 618 | applymoves_error: |
| 600 | readmodifier(char c) | 619 | DBG_LOG("applymoves error\n"); |
| 601 | { | 620 | return -1; |
| 602 | switch (c) { | ||
| 603 | case '1': /* Fallthrough */ | ||
| 604 | case '2': /* Fallthrough */ | ||
| 605 | case '3': | ||
| 606 | return c - '0' - 1; | ||
| 607 | case '\'': | ||
| 608 | return 2; | ||
| 609 | default: | ||
| 610 | return 0; | ||
| 611 | } | ||
| 612 | } | 621 | } |
| 613 | 622 | ||
| 614 | _static uint8_t | 623 | trans_t |
| 615 | readtrans(char *buf) | 624 | cube_readtrans(char *buf) |
| 616 | { | 625 | { |
| 617 | uint8_t t; | 626 | trans_t t; |
| 618 | 627 | ||
| 619 | for (t = 0; t < 48; t++) | 628 | for (t = 0; t < 48; t++) |
| 620 | if (!strncmp(buf, transstr[t], 11)) | 629 | if (!strncmp(buf, transstr[t], 11)) |
| 621 | return t; | 630 | return t; |
| 622 | 631 | ||
| 623 | DBG_LOG("readtrans error\n"); | 632 | return -1; |
| 624 | return _error; | ||
| 625 | } | 633 | } |
| 626 | 634 | ||
| 627 | _static int | 635 | char * |
| 628 | writemoves(uint8_t *m, int n, char *buf) | 636 | cube_movestr(move_t m) |
| 629 | { | 637 | { |
| 630 | int i; | 638 | return movestr[m]; |
| 631 | size_t len; | ||
| 632 | char *b, *s; | ||
| 633 | |||
| 634 | for (i = 0, b = buf; i < n; i++, b++) { | ||
| 635 | s = movestr[m[i]]; | ||
| 636 | len = strlen(s); | ||
| 637 | memcpy(b, s, len); | ||
| 638 | b += len; | ||
| 639 | *b = ' '; | ||
| 640 | } | ||
| 641 | |||
| 642 | if (b != buf) | ||
| 643 | b--; /* Remove last space */ | ||
| 644 | *b = '\0'; | ||
| 645 | |||
| 646 | return b - buf; | ||
| 647 | } | 639 | } |
| 648 | 640 | ||
| 649 | _static void | 641 | char * |
| 650 | writetrans(uint8_t t, char *buf) | 642 | cube_transstr(trans_t t) |
| 651 | { | 643 | { |
| 652 | if (t >= 48) | 644 | return transstr[t]; |
| 653 | memcpy(buf, "error trans", 11); | ||
| 654 | else | ||
| 655 | memcpy(buf, transstr[t], 11); | ||
| 656 | buf[11] = '\0'; | ||
| 657 | } | 645 | } |
| 658 | 646 | ||
| 659 | _static cube_t | 647 | move_t |
| 660 | move(cube_t c, move_t m) | 648 | cube_inversemove(move_t m) |
| 661 | { | 649 | { |
| 662 | return cube_compose(c, move_table[m]); | 650 | return m - 2*(m%3) + 2; |
| 663 | } | 651 | } |
| 664 | 652 | ||
| 665 | _static_inline cube_t | 653 | trans_t |
| 666 | invertco(cube_t c) | 654 | cube_inversetrans(trans_t t) |
| 667 | { | ||
| 668 | uint8_t i, piece, orien; | ||
| 669 | cube_t ret; | ||
| 670 | |||
| 671 | ret = c; | ||
| 672 | for (i = 0; i < 8; i++) { | ||
| 673 | piece = c.corner[i]; | ||
| 674 | orien = ((piece << 1) | (piece >> 1)) & _cobits2; | ||
| 675 | ret.corner[i] = (piece & _pbits) | orien; | ||
| 676 | } | ||
| 677 | |||
| 678 | return ret; | ||
| 679 | } | ||
| 680 | |||
| 681 | |||
| 682 | _static cube_t | ||
| 683 | transform(cube_t c, trans_t t) | ||
| 684 | { | ||
| 685 | cube_t tcube, tinv; | ||
| 686 | |||
| 687 | tcube = trans_table[t][NORMAL]; | ||
| 688 | tinv = trans_table[t][INVERSE]; | ||
| 689 | |||
| 690 | return t < 24 ? | ||
| 691 | cube_compose(cube_compose(tcube, c), tinv) : | ||
| 692 | invertco(cube_compose(cube_compose(tcube, c), tinv)); | ||
| 693 | } | ||
| 694 | |||
| 695 | /* TODO: expose or remove, maybe add inverse move */ | ||
| 696 | _static_inline uint8_t inverse_trans(uint8_t); | ||
| 697 | |||
| 698 | _static_inline uint8_t | ||
| 699 | inverse_trans(uint8_t t) | ||
| 700 | { | 655 | { |
| 701 | return inverse_trans_table[t]; | 656 | return inverse_trans_table[t]; |
| 702 | } | 657 | } |
