aboutsummaryrefslogtreecommitdiff
path: root/cube.c
diff options
context:
space:
mode:
Diffstat (limited to 'cube.c')
-rw-r--r--cube.c643
1 files changed, 299 insertions, 344 deletions
diff --git a/cube.c b/cube.c
index ba65580..f44a7df 100644
--- a/cube.c
+++ b/cube.c
@@ -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 *); 48readco(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
62readcp(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
76readeo(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
88readep(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
101read_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
137readpiece_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
154read_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
169writepiece_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
192write_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
221write_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
242readmove(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
263readmodifier(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
278invertco(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
294permsign(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
52cube_t 306cube_t
53cube_new(void) 307cube_new(void)
@@ -250,51 +504,22 @@ cube_inverse(cube_t cube)
250} 504}
251 505
252cube_t 506cube_t
253applymoves(cube_t cube, char *buf) 507cube_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
276applymoves_finish:
277 return ret;
278
279applymoves_error:
280 DBG_LOG("applymoves error\n");
281 return zero;
282} 510}
283 511
284cube_t 512cube_t
285applytrans(cube_t cube, char *buf) 513cube_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
300int64_t 525int64_t
@@ -368,335 +593,65 @@ write_error:
368 buf[len+1] = '\0'; 593 buf[len+1] = '\0';
369} 594}
370 595
371_static int 596int
372permsign(uint8_t *a, int n) 597cube_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
385readco(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
399readcp(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
413readeo(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
425readep(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
438read_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
474readpiece_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
491read_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
506writepiece_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
529write_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
558write_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++) { 615applymoves_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
579readmove(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 618applymoves_error:
600readmodifier(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 623trans_t
615readtrans(char *buf) 624cube_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 635char *
628writemoves(uint8_t *m, int n, char *buf) 636cube_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 641char *
650writetrans(uint8_t t, char *buf) 642cube_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 647move_t
660move(cube_t c, move_t m) 648cube_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 653trans_t
666invertco(cube_t c) 654cube_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
683transform(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
699inverse_trans(uint8_t t)
700{ 655{
701 return inverse_trans_table[t]; 656 return inverse_trans_table[t];
702} 657}

Generated with cgit - Back to sebastiano.tronto.net