aboutsummaryrefslogtreecommitdiff
path: root/src/core/moves.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/moves.h')
-rw-r--r--src/core/moves.h222
1 files changed, 216 insertions, 6 deletions
diff --git a/src/core/moves.h b/src/core/moves.h
index 9c8cc90..6169c6e 100644
--- a/src/core/moves.h
+++ b/src/core/moves.h
@@ -11,6 +11,8 @@ STATIC bool moves_struct_equal(
11STATIC long long comparemoves(const char *, const char *); 11STATIC long long comparemoves(const char *, const char *);
12STATIC uint8_t readmodifier(char); 12STATIC uint8_t readmodifier(char);
13STATIC int64_t writemoves(size_t, const uint8_t *, size_t, char *); 13STATIC int64_t writemoves(size_t, const uint8_t *, size_t, char *);
14STATIC int64_t writemoves_struct(
15 const moves_struct_t [static 1], size_t, char *);
14 16
15STATIC_INLINE bool allowednextmove(uint8_t, uint8_t); 17STATIC_INLINE bool allowednextmove(uint8_t, uint8_t);
16STATIC bool allowedmoves(size_t, const uint8_t *); 18STATIC bool allowedmoves(size_t, const uint8_t *);
@@ -23,6 +25,7 @@ STATIC_INLINE uint8_t moveopposite(uint8_t);
23STATIC_INLINE uint8_t reorient_move(uint8_t, uint8_t); 25STATIC_INLINE uint8_t reorient_move(uint8_t, uint8_t);
24STATIC_INLINE uint8_t inverse_reorient_move(uint8_t, uint8_t); 26STATIC_INLINE uint8_t inverse_reorient_move(uint8_t, uint8_t);
25STATIC_INLINE uint8_t movefollow(uint8_t); 27STATIC_INLINE uint8_t movefollow(uint8_t);
28STATIC uint8_t transform_move_basic(uint8_t, uint8_t);
26STATIC uint8_t transform_move(uint8_t, uint8_t); 29STATIC uint8_t transform_move(uint8_t, uint8_t);
27 30
28STATIC cube_t move(cube_t, uint8_t); 31STATIC cube_t move(cube_t, uint8_t);
@@ -31,6 +34,12 @@ STATIC uint8_t inverse_move(uint8_t);
31STATIC void sortparallel_moves(size_t, uint8_t*); 34STATIC void sortparallel_moves(size_t, uint8_t*);
32STATIC bool are_lastmoves_singlecw(size_t, const uint8_t*); 35STATIC bool are_lastmoves_singlecw(size_t, const uint8_t*);
33 36
37STATIC int64_t move_variations(const char *, const char *, size_t, char *);
38STATIC int64_t move_variations_lastqt(
39 const moves_struct_t [static 1], size_t, char *);
40STATIC int64_t move_variations_unniss(
41 const moves_struct_t [static 1], size_t, char *);
42
34#define FOREACH_READMOVE(ARG_BUF, ARG_MOVE, ARG_C, ARG_MAX, \ 43#define FOREACH_READMOVE(ARG_BUF, ARG_MOVE, ARG_C, ARG_MAX, \
35 RET_ERROR, ARG_ACTION) \ 44 RET_ERROR, ARG_ACTION) \
36 const char *VAR_B; \ 45 const char *VAR_B; \
@@ -160,7 +169,7 @@ readmoves(
160STATIC int64_t 169STATIC int64_t
161readmoves_struct(const char *moves, moves_struct_t ret[static 1]) 170readmoves_struct(const char *moves, moves_struct_t ret[static 1])
162{ 171{
163 return readmoves(moves, MOVES_STRUCT_MAXLEN, MOVES_STRUCT_MAXLEN, 172 return readmoves(moves, NISSY_SIZE_MOVES, NISSY_SIZE_MOVES,
164 &ret->nnormal, &ret->ninverse, ret->normal, ret->inverse); 173 &ret->nnormal, &ret->ninverse, ret->normal, ret->inverse);
165} 174}
166 175
@@ -270,6 +279,51 @@ writemoves_error:
270 return NISSY_ERROR_BUFFER_SIZE; 279 return NISSY_ERROR_BUFFER_SIZE;
271} 280}
272 281
282STATIC int64_t
283writemoves_struct(
284 const moves_struct_t moves[static 1],
285 size_t buf_size,
286 char *buf
287)
288{
289 int64_t w, u;
290
291 w = 0;
292 if (moves->nnormal > 0) {
293 w = writemoves(moves->nnormal, moves->normal, buf_size, buf);
294 if (w < 0)
295 goto writemoves_struct_error;
296 }
297
298 u = 0;
299 if (moves->ninverse > 0) {
300 if (moves->nnormal > 0) {
301 if ((size_t)w >= buf_size)
302 goto writemoves_struct_error;
303 buf[w++] = ' ';
304 }
305 if ((size_t)w >= buf_size)
306 goto writemoves_struct_error;
307 buf[w++] = '(';
308
309 u = writemoves(moves->ninverse, moves->inverse,
310 buf_size-w, buf+w);
311 if (u < 0)
312 goto writemoves_struct_error;
313
314 if ((size_t)w >= buf_size)
315 goto writemoves_struct_error;
316 buf[w + (u++)] = ')';
317 }
318
319 buf[u+w] = '\0';
320 return u+w;
321
322writemoves_struct_error:
323 buf[w] = '\0';
324 return NISSY_ERROR_BUFFER_SIZE;
325}
326
273STATIC_INLINE bool 327STATIC_INLINE bool
274allowednextmove(uint8_t m1, uint8_t m2) 328allowednextmove(uint8_t m1, uint8_t m2)
275{ 329{
@@ -408,14 +462,12 @@ move(cube_t c, uint8_t m)
408} 462}
409 463
410STATIC uint8_t 464STATIC uint8_t
411transform_move(uint8_t m, uint8_t t) 465transform_move_basic(uint8_t m, uint8_t t)
412{ 466{
413 uint8_t a, base, modifier; 467 uint8_t a, base, modifier;
414 468
415 if (m > MOVE_B3) { 469 if (t > 47) {
416 LOG("transform_move: attempting to transform %s, but " 470 LOG("transform_move: invalid trans %" PRIu8 "\n", t);
417 "transofrmations are only supported for basic moves\n",
418 movestr[m]);
419 return UINT8_ERROR; 471 return UINT8_ERROR;
420 } 472 }
421 473
@@ -431,6 +483,27 @@ transform_move(uint8_t m, uint8_t t)
431 return base + modifier; 483 return base + modifier;
432} 484}
433 485
486STATIC uint8_t
487transform_move(uint8_t m, uint8_t t)
488{
489 if (m <= MOVE_B3)
490 return transform_move_basic(m, t);
491
492 if (m >= MOVE_Uw && m <= MOVE_Bw3)
493 return 18+transform_move_basic(m-18, t);
494
495 if (m >= MOVE_M && m <= MOVE_E3)
496 return basic_to_slice[
497 transform_move_basic(slice_to_basic[m], t)];
498
499 if (m >= MOVE_x && m <= MOVE_z3)
500 return basic_to_rotation[
501 transform_move_basic(rotation_to_basic[m], t)];
502
503 LOG("transform_move: invalid move %" PRIu8 "\n", m);
504 return UINT8_ERROR;
505}
506
434/* Applies the INVERSE of m BEFORE the scramble corresponding to c */ 507/* Applies the INVERSE of m BEFORE the scramble corresponding to c */
435STATIC cube_t 508STATIC cube_t
436premove(cube_t c, uint8_t m) 509premove(cube_t c, uint8_t m)
@@ -509,3 +582,140 @@ are_lastmoves_singlecw(size_t n, const uint8_t *moves)
509 582
510 return isbase(moves[n-1]) && (!two || isbase(moves[n-2])); 583 return isbase(moves[n-1]) && (!two || isbase(moves[n-2]));
511} 584}
585
586STATIC int64_t
587move_variations(
588 const char *moves,
589 const char *variation,
590 size_t result_size,
591 char *result
592)
593{
594 moves_struct_t m;
595 int64_t err;
596
597 err = readmoves_struct(moves, &m);
598 if (err < 0) {
599 LOG("[variations] Error reading moves.\n");
600 return err;
601 }
602
603 if (!strcmp(variation, "lastqt")) {
604 return move_variations_lastqt(&m, result_size, result);
605 } else if (!strcmp(variation, "unniss")) {
606 return move_variations_unniss(&m, result_size, result);
607 } else {
608 LOG("[variations] Error: unknown variation '%s'\n", variation);
609 return NISSY_ERROR_INVALID_VARIATION;
610 }
611}
612
613STATIC int64_t
614move_variations_lastqt(
615 const moves_struct_t s[static 1],
616 size_t result_size,
617 char *result
618)
619{
620 uint8_t n1, n2, i1, i2, swapn1, swapn2, swapi1, swapi2, i, j, k, l;
621 int8_t in1, in2, ii1, ii2;
622 int64_t err, count;
623 size_t u;
624 moves_struct_t ss;
625
626 in1 = s->nnormal-1;
627 in2 = s->nnormal-2;
628 ii1 = s->ninverse-1;
629 ii2 = s->ninverse-2;
630
631 n1 = in1 >= 0 ? s->normal[in1] : UINT8_ERROR;
632 n2 = in2 >= 0 ? s->normal[in2] : UINT8_ERROR;
633 i1 = ii1 >= 0 ? s->inverse[ii1] : UINT8_ERROR;
634 i2 = ii2 >= 0 ? s->inverse[ii2] : UINT8_ERROR;
635
636 swapn1 = in1 >= 0 && n1 % 3 != 1 ? 1 : 0;
637 swapn2 = swapn1 && in2 >= 0 && n2 % 3 != 1 && parallel(n1, n2) ? 1 : 0;
638 swapi1 = ii1 >= 0 && i1 % 3 != 1 ? 1 : 0;
639 swapi2 = swapi1 && ii2 >= 0 && i2 % 3 != 1 && parallel(i1, i2) ? 1 : 0;
640
641 /* Reset ending qt to base so that they are sorted */
642 ss = *s;
643 if (swapn1 == 1) ss.normal[in1] = 3*movebase(n1);
644 if (swapn2 == 1) ss.normal[in2] = 3*movebase(n2);
645 if (swapi1 == 1) ss.inverse[ii1] = 3*movebase(i1);
646 if (swapi2 == 1) ss.inverse[ii2] = 3*movebase(i2);
647
648 u = 0;
649 count = 0;
650 for (i = 0; i <= swapn2; i++) {
651 if (i == 1) ss.normal[in2] += 2;
652 for (j = 0; j <= swapn1; j++) {
653 if (j == 1) ss.normal[in1] += 2;
654 for (k = 0; k <= swapi2; k++) {
655 if (k == 1) ss.inverse[ii2] += 2;
656 for (l = 0; l <= swapi1; l++) {
657 if (l == 1) ss.inverse[ii1] += 2;
658
659 err = writemoves_struct(
660 &ss, result_size-u, result+u);
661 if (err < 0)
662 goto lastqt_error;
663 u += err;
664 count++;
665
666 if (u >= result_size)
667 goto lastqt_error;
668 result[u++] = '\n';
669 result[u] = '\0';
670
671 if (l == 1) ss.inverse[ii1] -= 2;
672 }
673 if (k == 1) ss.inverse[ii2] -= 2;
674 }
675 if (j == 1) ss.normal[in1] -= 2;
676 }
677 if (i == 1) ss.normal[in2] -= 2;
678 }
679
680 return count;
681
682lastqt_error:
683 LOG("[variations] Error writing result.\n");
684 return NISSY_ERROR_BUFFER_SIZE;
685}
686
687STATIC int64_t
688move_variations_unniss(
689 const moves_struct_t s[static 1],
690 size_t result_size,
691 char *result
692)
693{
694 size_t i, tot;
695 uint8_t res[NISSY_SIZE_MOVES];
696 int64_t err;
697
698 tot = s->nnormal + s->ninverse;
699 if (tot > NISSY_SIZE_MOVES) {
700 LOG("[variations] Error: %zu total moves, more than maximum "
701 "allowed %zu", tot, NISSY_SIZE_MOVES);
702 return NISSY_ERROR_BUFFER_SIZE;
703 }
704
705 for (i = 0; i < s->nnormal; i++)
706 res[i] = s->normal[i];
707 for (i = 0; i < s->ninverse; i++)
708 res[i+s->nnormal] = inverse_move(s->inverse[s->ninverse-i-1]);
709
710 err = writemoves(tot, res, result_size, result);
711 if (err < 0 || (size_t)err > result_size)
712 goto unniss_error;
713
714 result[err++] = '\n';
715 result[err] = '\0';
716 return 1;
717
718unniss_error:
719 LOG("[variations] Error writing result.\n");
720 return NISSY_ERROR_BUFFER_SIZE;
721}

Generated with cgit - Back to sebastiano.tronto.net