aboutsummaryrefslogtreecommitdiff
path: root/src/cube_generic.h
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2024-06-09 20:06:19 +0200
committerSebastiano Tronto <sebastiano@tronto.net>2024-06-09 20:06:19 +0200
commit0b1930307f41db3ea7552d6b2f4666b33c64d26a (patch)
tree6a2558e391f5cc14fa22770cb2791e4a85d84e5e /src/cube_generic.h
parentb218c803ae1110b08b4896be0a59177e280c9091 (diff)
downloadnissy-core-0b1930307f41db3ea7552d6b2f4666b33c64d26a.tar.gz
nissy-core-0b1930307f41db3ea7552d6b2f4666b33c64d26a.zip
More cleanup
Diffstat (limited to 'src/cube_generic.h')
-rw-r--r--src/cube_generic.h488
1 files changed, 14 insertions, 474 deletions
diff --git a/src/cube_generic.h b/src/cube_generic.h
index a90aa17..844b328 100644
--- a/src/cube_generic.h
+++ b/src/cube_generic.h
@@ -1,62 +1,27 @@
1#define _move(M, c) compose(c, _move_cube_ ## M) 1#define _move(M, c) compose(c, _move_cube_ ## M)
2#define _premove(M, c) compose(_move_cube_ ## M, c) 2#define _premove(M, c) compose(_move_cube_ ## M, c)
3 3
4_static cube_t cubefromarray(uint8_t [static 8], uint8_t [static 12]); 4_static cube_t solvedcube();
5_static bool isconsistent(cube_t);
6_static bool issolvable(cube_t);
7_static bool issolved(cube_t);
8_static bool iserror(cube_t);
9_static cube_t applymoves(cube_t, const char *);
10_static cube_t applytrans(cube_t, const char *);
11
5_static int permsign(uint8_t *, int); 12_static int permsign(uint8_t *, int);
6_static uint8_t readco(const char *);
7_static uint8_t readcp(const char *);
8_static uint8_t readeo(const char *);
9_static uint8_t readep(const char *);
10_static cube_t readcube_B32(const char *);
11_static cube_t readcube_H48(const char *);
12_static uint8_t readpiece_LST(const char **);
13_static cube_t readcube_LST(const char *);
14_static int writepiece_LST(uint8_t, char *);
15_static void writecube_B32(cube_t, char *);
16_static void writecube_H48(cube_t, char *);
17_static void writecube_LST(cube_t, char *);
18_static uint8_t b32toedge(char);
19_static uint8_t b32tocorner(char);
20_static char edgetob32(uint8_t);
21_static char cornertob32(uint8_t);
22_static uint8_t readmove(char);
23_static uint8_t readmodifier(char);
24_static uint8_t readtrans(const char *);
25_static int writemoves(uint8_t *, int, char *);
26_static void writetrans(uint8_t, char *);
27_static cube_t move(cube_t, uint8_t); 13_static cube_t move(cube_t, uint8_t);
28_static cube_t transform_edges(cube_t, uint8_t); 14_static cube_t transform_edges(cube_t, uint8_t);
29_static cube_t transform_corners(cube_t, uint8_t); 15_static cube_t transform_corners(cube_t, uint8_t);
30_static cube_t transform(cube_t, uint8_t); 16_static cube_t transform(cube_t, uint8_t);
31 17
32_static struct { 18_static cube_t
33 const char *name; 19solvedcube()
34 cube_t (*read)(const char *);
35 void (*write)(cube_t, char *);
36} ioformat[] =
37{
38 { .name = "B32", .read = readcube_B32, .write = writecube_B32 },
39 { .name = "LST", .read = readcube_LST, .write = writecube_LST },
40 { .name = "H48", .read = readcube_H48, .write = writecube_H48 },
41 { .name = "NONE", .read = NULL, .write = NULL },
42};
43
44_static_inline cube_t
45cubefromarray(uint8_t c[static 8], uint8_t e[static 12])
46{
47 return static_cube(
48 c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7],
49 e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7],
50 e[8], e[9], e[10], e[11]);
51}
52
53cube_t
54solvedcube(void)
55{ 20{
56 return solved; 21 return solved;
57} 22}
58 23
59bool 24_static bool
60isconsistent(cube_t cube) 25isconsistent(cube_t cube)
61{ 26{
62 uint8_t i, p, e, piece, corner[8], edge[12]; 27 uint8_t i, p, e, piece, corner[8], edge[12];
@@ -112,7 +77,7 @@ inconsistent_co:
112 return false; 77 return false;
113} 78}
114 79
115bool 80_static bool
116issolvable(cube_t cube) 81issolvable(cube_t cube)
117{ 82{
118 uint8_t i, eo, co, piece, edge[12], corner[8], ep[12], cp[8]; 83 uint8_t i, eo, co, piece, edge[12], corner[8], ep[12], cp[8];
@@ -170,32 +135,7 @@ iserror(cube_t cube)
170 return equal(cube, zero); 135 return equal(cube, zero);
171} 136}
172 137
173cube_t 138_static cube_t
174inverse(cube_t cube)
175{
176 uint8_t i, piece, orien, e[12], c[8], edge[12], corner[8];
177
178 DBG_ASSERT(isconsistent(cube), zero,
179 "inverse error: inconsistent cube\n");
180
181 pieces(&cube, corner, edge);
182
183 for (i = 0; i < 12; i++) {
184 piece = edge[i];
185 orien = piece & _eobit;
186 e[piece & _pbits] = i | orien;
187 }
188
189 for (i = 0; i < 8; i++) {
190 piece = corner[i];
191 orien = ((piece << 1) | (piece >> 1)) & _cobits2;
192 c[piece & _pbits] = i | orien;
193 }
194
195 return cubefromarray(c, e);
196}
197
198cube_t
199applymoves(cube_t cube, const char *buf) 139applymoves(cube_t cube, const char *buf)
200{ 140{
201 uint8_t r, m; 141 uint8_t r, m;
@@ -224,7 +164,7 @@ applymoves_error:
224 return zero; 164 return zero;
225} 165}
226 166
227cube_t 167_static cube_t
228applytrans(cube_t cube, const char *buf) 168applytrans(cube_t cube, const char *buf)
229{ 169{
230 uint8_t t; 170 uint8_t t;
@@ -237,49 +177,6 @@ applytrans(cube_t cube, const char *buf)
237 return transform(cube, t); 177 return transform(cube, t);
238} 178}
239 179
240cube_t
241readcube(const char *format, const char *buf)
242{
243 int i;
244
245 for (i = 0; ioformat[i].read != NULL; i++)
246 if (!strcmp(format, ioformat[i].name))
247 return ioformat[i].read(buf);
248
249 DBG_LOG("Cannot read cube in the given format\n");
250 return zero;
251}
252
253void
254writecube(const char *format, cube_t cube, char *buf)
255{
256 char *errormsg;
257 size_t len;
258
259 if (!isconsistent(cube)) {
260 errormsg = "ERROR: cannot write inconsistent cube";
261 goto writecube_error;
262 }
263
264 int i;
265
266 for (i = 0; ioformat[i].write != NULL; i++) {
267 if (!strcmp(format, ioformat[i].name)) {
268 ioformat[i].write(cube, buf);
269 return;
270 }
271 }
272
273 errormsg = "ERROR: cannot write cube in the given format";
274
275writecube_error:
276 DBG_LOG("writecube error, see stdout for details\n");
277 len = strlen(errormsg);
278 memcpy(buf, errormsg, len);
279 buf[len] = '\n';
280 buf[len+1] = '\0';
281}
282
283_static int 180_static int
284permsign(uint8_t *a, int n) 181permsign(uint8_t *a, int n)
285{ 182{
@@ -293,363 +190,6 @@ permsign(uint8_t *a, int n)
293 return ret % 2; 190 return ret % 2;
294} 191}
295 192
296_static uint8_t
297readco(const char *str)
298{
299 if (*str == '0')
300 return 0;
301 if (*str == '1')
302 return _ctwist_cw;
303 if (*str == '2')
304 return _ctwist_ccw;
305
306 DBG_LOG("Error reading CO\n");
307 return _error;
308}
309
310_static uint8_t
311readcp(const char *str)
312{
313 uint8_t c;
314
315 for (c = 0; c < 8; c++)
316 if (!strncmp(str, cornerstr[c], 3) ||
317 !strncmp(str, cornerstralt[c], 3))
318 return c;
319
320 DBG_LOG("Error reading CP\n");
321 return _error;
322}
323
324_static uint8_t
325readeo(const char *str)
326{
327 if (*str == '0')
328 return 0;
329 if (*str == '1')
330 return _eflip;
331
332 DBG_LOG("Error reading EO\n");
333 return _error;
334}
335
336_static uint8_t
337readep(const char *str)
338{
339 uint8_t e;
340
341 for (e = 0; e < 12; e++)
342 if (!strncmp(str, edgestr[e], 2))
343 return e;
344
345 DBG_LOG("Error reading EP\n");
346 return _error;
347}
348
349_static cube_t
350readcube_B32(const char *buf)
351{
352 int i;
353 uint8_t c[8], e[12];
354
355 for (i = 0; i < 8; i++) {
356 c[i] = b32tocorner(buf[i]);
357 DBG_ASSERT(c[i] < 255, zero,
358 "Error reading B32 corner %d (char %d)\n", i, i);
359 }
360
361 for (i = 0; i < 12; i++) {
362 e[i] = b32toedge(buf[i+9]);
363 DBG_ASSERT(e[i] < 255, zero,
364 "Error reading B32 edge %d (char %d)\n", i, i+9);
365 }
366
367 return cubefromarray(c, e);
368}
369
370_static cube_t
371readcube_H48(const char *buf)
372{
373 int i;
374 uint8_t piece, orient, c[8], e[12];
375 const char *b;
376
377 b = buf;
378
379 for (i = 0; i < 12; i++) {
380 while (*b == ' ' || *b == '\t' || *b == '\n')
381 b++;
382 if ((piece = readep(b)) == _error)
383 return zero;
384 b += 2;
385 if ((orient = readeo(b)) == _error)
386 return zero;
387 b++;
388 e[i] = piece | orient;
389 }
390 for (i = 0; i < 8; i++) {
391 while (*b == ' ' || *b == '\t' || *b == '\n')
392 b++;
393 if ((piece = readcp(b)) == _error)
394 return zero;
395 b += 3;
396 if ((orient = readco(b)) == _error)
397 return zero;
398 b++;
399 c[i] = piece | orient;
400 }
401
402 return cubefromarray(c, e);
403}
404
405_static uint8_t
406readpiece_LST(const char **b)
407{
408 uint8_t ret;
409 bool read;
410
411 while (**b == ',' || **b == ' ' || **b == '\t' || **b == '\n')
412 (*b)++;
413
414 for (ret = 0, read = false; **b >= '0' && **b <= '9'; (*b)++) {
415 read = true;
416 ret = ret * 10 + (**b) - '0';
417 }
418
419 return read ? ret : _error;
420}
421
422_static cube_t
423readcube_LST(const char *buf)
424{
425 int i;
426 uint8_t c[8], e[12];
427
428 for (i = 0; i < 8; i++)
429 c[i] = readpiece_LST(&buf);
430
431 for (i = 0; i < 12; i++)
432 e[i] = readpiece_LST(&buf);
433
434 return cubefromarray(c, e);
435}
436
437_static int
438writepiece_LST(uint8_t piece, char *buf)
439{
440 char digits[3];
441 int i, len;
442
443 len = 0;
444 while (piece != 0) {
445 digits[len++] = (piece % 10) + '0';
446 piece /= 10;
447 }
448
449 if (len == 0)
450 digits[len++] = '0';
451
452 for (i = 0; i < len; i++)
453 buf[i] = digits[len-i-1];
454
455 buf[len] = ',';
456 buf[len+1] = ' ';
457
458 return len+2;
459}
460
461_static void
462writecube_B32(cube_t cube, char *buf)
463{
464 int i;
465 uint8_t corner[8], edge[12];
466
467 pieces(&cube, corner, edge);
468
469 for (i = 0; i < 8; i++)
470 buf[i] = cornertob32(corner[i]);
471
472 buf[8] = '=';
473
474 for (i = 0; i < 12; i++)
475 buf[i+9] = edgetob32(edge[i]);
476
477 buf[21] = '\0';
478}
479
480_static void
481writecube_H48(cube_t cube, char *buf)
482{
483 uint8_t piece, perm, orient, corner[8], edge[12];
484 int i;
485
486 pieces(&cube, corner, edge);
487
488 for (i = 0; i < 12; i++) {
489 piece = edge[i];
490 perm = piece & _pbits;
491 orient = (piece & _eobit) >> _eoshift;
492 buf[4*i ] = edgestr[perm][0];
493 buf[4*i + 1] = edgestr[perm][1];
494 buf[4*i + 2] = orient + '0';
495 buf[4*i + 3] = ' ';
496 }
497 for (i = 0; i < 8; i++) {
498 piece = corner[i];
499 perm = piece & _pbits;
500 orient = (piece & _cobits) >> _coshift;
501 buf[48 + 5*i ] = cornerstr[perm][0];
502 buf[48 + 5*i + 1] = cornerstr[perm][1];
503 buf[48 + 5*i + 2] = cornerstr[perm][2];
504 buf[48 + 5*i + 3] = orient + '0';
505 buf[48 + 5*i + 4] = ' ';
506 }
507
508 buf[48+39] = '\0';
509}
510
511_static void
512writecube_LST(cube_t cube, char *buf)
513{
514 int i;
515 size_t ptr;
516 uint8_t piece, corner[8], edge[12];
517
518 ptr = 0;
519 pieces(&cube, corner, edge);
520
521 for (i = 0; i < 8; i++) {
522 piece = corner[i];
523 ptr += writepiece_LST(piece, buf + ptr);
524 }
525
526 for (i = 0; i < 12; i++) {
527 piece = edge[i];
528 ptr += writepiece_LST(piece, buf + ptr);
529 }
530
531 *(buf+ptr-2) = 0;
532}
533
534_static uint8_t
535b32toedge(char c)
536{
537 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'g'))
538 return 255;
539
540 return c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a');
541}
542
543_static uint8_t
544b32tocorner(char c) {
545 uint8_t val;
546
547 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'g'))
548 return 255;
549
550 val = c <= 'Z' ? (uint8_t)(c - 'A') : (uint8_t)(c - 'a') + 26;
551
552 return (val & 7) | ((val & 24) << 2);
553}
554
555_static char
556edgetob32(uint8_t edge)
557{
558 return edge <= 26 ? 'A' + (char)edge : 'a' + (char)(edge - 26);
559}
560
561_static char
562cornertob32(uint8_t corner)
563{
564 uint8_t val;
565
566 val = (corner & 7) | ((corner & 96) >> 2);
567
568 return val <= 26 ? 'A' + (char)val : 'a' + (char)(val - 26);
569}
570
571_static uint8_t
572readmove(char c)
573{
574 switch (c) {
575 case 'U':
576 return _move_U;
577 case 'D':
578 return _move_D;
579 case 'R':
580 return _move_R;
581 case 'L':
582 return _move_L;
583 case 'F':
584 return _move_F;
585 case 'B':
586 return _move_B;
587 default:
588 return _error;
589 }
590}
591
592_static uint8_t
593readmodifier(char c)
594{
595 switch (c) {
596 case '1': /* Fallthrough */
597 case '2': /* Fallthrough */
598 case '3':
599 return c - '0' - 1;
600 case '\'':
601 return 2;
602 default:
603 return 0;
604 }
605}
606
607_static uint8_t
608readtrans(const char *buf)
609{
610 uint8_t t;
611
612 for (t = 0; t < 48; t++)
613 if (!strncmp(buf, transstr[t], 11))
614 return t;
615
616 DBG_LOG("readtrans error\n");
617 return _error;
618}
619
620_static int
621writemoves(uint8_t *m, int n, char *buf)
622{
623 int i;
624 size_t len;
625 const char *s;
626 char *b;
627
628 for (i = 0, b = buf; i < n; i++, b++) {
629 s = movestr[m[i]];
630 len = strlen(s);
631 memcpy(b, s, len);
632 b += len;
633 *b = ' ';
634 }
635
636 if (b != buf)
637 b--; /* Remove last space */
638 *b = '\0';
639
640 return b - buf;
641}
642
643_static void
644writetrans(uint8_t t, char *buf)
645{
646 if (t >= 48)
647 memcpy(buf, "error trans", 11);
648 else
649 memcpy(buf, transstr[t], 11);
650 buf[11] = '\0';
651}
652
653_static cube_t 193_static cube_t
654move(cube_t c, uint8_t m) 194move(cube_t c, uint8_t m)
655{ 195{

Generated with cgit - Back to sebastiano.tronto.net