aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/constants.h66
-rw-r--r--src/core/core_types.h6
-rw-r--r--src/core/moves.h222
-rw-r--r--src/nissy.c26
-rw-r--r--src/nissy.h41
-rw-r--r--src/solvers/solutions.h4
-rw-r--r--src/solvers/solutions_types_macros.h6
7 files changed, 356 insertions, 15 deletions
diff --git a/src/core/constants.h b/src/core/constants.h
index 26f6916..d8f2471 100644
--- a/src/core/constants.h
+++ b/src/core/constants.h
@@ -845,3 +845,69 @@ STATIC equivalent_moves_t equivalent_moves_table[] = {
845 [MOVE_z2] = {{UINT8_MAX}, {2, 2, UINT8_MAX}}, 845 [MOVE_z2] = {{UINT8_MAX}, {2, 2, UINT8_MAX}},
846 [MOVE_z3] = {{UINT8_MAX}, {2, 2, 2, UINT8_MAX}}, 846 [MOVE_z3] = {{UINT8_MAX}, {2, 2, 2, UINT8_MAX}},
847}; 847};
848
849STATIC uint8_t slice_to_basic[] = {
850 [MOVE_M] = MOVE_L,
851 [MOVE_M2] = MOVE_L2,
852 [MOVE_M3] = MOVE_L3,
853 [MOVE_S] = MOVE_F,
854 [MOVE_S2] = MOVE_F2,
855 [MOVE_S3] = MOVE_F3,
856 [MOVE_E] = MOVE_D,
857 [MOVE_E2] = MOVE_D2,
858 [MOVE_E3] = MOVE_D3,
859};
860
861STATIC uint8_t basic_to_slice[] = {
862 [MOVE_U] = MOVE_E3,
863 [MOVE_U2] = MOVE_E2,
864 [MOVE_U3] = MOVE_E,
865 [MOVE_D] = MOVE_E,
866 [MOVE_D2] = MOVE_E2,
867 [MOVE_D3] = MOVE_E3,
868 [MOVE_R] = MOVE_M3,
869 [MOVE_R2] = MOVE_M2,
870 [MOVE_R3] = MOVE_M,
871 [MOVE_L] = MOVE_M,
872 [MOVE_L2] = MOVE_M2,
873 [MOVE_L3] = MOVE_M3,
874 [MOVE_F] = MOVE_S,
875 [MOVE_F2] = MOVE_S2,
876 [MOVE_F3] = MOVE_S3,
877 [MOVE_B] = MOVE_S3,
878 [MOVE_B2] = MOVE_S2,
879 [MOVE_B3] = MOVE_S,
880};
881
882STATIC uint8_t rotation_to_basic[] = {
883 [MOVE_x] = MOVE_R,
884 [MOVE_x2] = MOVE_R2,
885 [MOVE_x3] = MOVE_R3,
886 [MOVE_y] = MOVE_U,
887 [MOVE_y2] = MOVE_U2,
888 [MOVE_y3] = MOVE_U3,
889 [MOVE_z] = MOVE_F,
890 [MOVE_z2] = MOVE_F2,
891 [MOVE_z3] = MOVE_F3,
892};
893
894STATIC uint8_t basic_to_rotation[] = {
895 [MOVE_U] = MOVE_y,
896 [MOVE_U2] = MOVE_y2,
897 [MOVE_U3] = MOVE_y3,
898 [MOVE_D] = MOVE_y3,
899 [MOVE_D2] = MOVE_y2,
900 [MOVE_D3] = MOVE_y,
901 [MOVE_R] = MOVE_x,
902 [MOVE_R2] = MOVE_x2,
903 [MOVE_R3] = MOVE_x3,
904 [MOVE_L] = MOVE_x3,
905 [MOVE_L2] = MOVE_x2,
906 [MOVE_L3] = MOVE_x,
907 [MOVE_F] = MOVE_z,
908 [MOVE_F2] = MOVE_z2,
909 [MOVE_F3] = MOVE_z3,
910 [MOVE_B] = MOVE_z3,
911 [MOVE_B2] = MOVE_z2,
912 [MOVE_B3] = MOVE_z,
913};
diff --git a/src/core/core_types.h b/src/core/core_types.h
index 19a9f42..53cc95e 100644
--- a/src/core/core_types.h
+++ b/src/core/core_types.h
@@ -1,5 +1,3 @@
1#define MOVES_STRUCT_MAXLEN 1000
2
3typedef struct { 1typedef struct {
4 cube_t cube; 2 cube_t cube;
5 uint8_t orientation; 3 uint8_t orientation;
@@ -8,6 +6,6 @@ typedef struct {
8typedef struct { 6typedef struct {
9 size_t nnormal; 7 size_t nnormal;
10 size_t ninverse; 8 size_t ninverse;
11 uint8_t normal[MOVES_STRUCT_MAXLEN]; 9 uint8_t normal[NISSY_SIZE_MOVES];
12 uint8_t inverse[MOVES_STRUCT_MAXLEN]; 10 uint8_t inverse[NISSY_SIZE_MOVES];
13} moves_struct_t; 11} moves_struct_t;
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}
diff --git a/src/nissy.c b/src/nissy.c
index 4b5d476..17ef960 100644
--- a/src/nissy.c
+++ b/src/nissy.c
@@ -149,6 +149,32 @@ nissy_applytrans_error:
149} 149}
150 150
151long long 151long long
152nissy_variations(
153 const char *moves,
154 const char *variation,
155 unsigned long long result_size,
156 char *result
157)
158{
159 if (moves == NULL) {
160 LOG("[variations] Error: 'moves' argument is NULL\n");
161 return NISSY_ERROR_NULL_POINTER;
162 }
163
164 if (variation == NULL) {
165 LOG("[variations] Error: 'variation' argument is NULL\n");
166 return NISSY_ERROR_NULL_POINTER;
167 }
168
169 if (result == NULL) {
170 LOG("[variations] Error: 'result' argument is NULL\n");
171 return NISSY_ERROR_NULL_POINTER;
172 }
173
174 return move_variations(moves, variation, result_size, result);
175}
176
177long long
152nissy_getcube( 178nissy_getcube(
153 long long ep, 179 long long ep,
154 long long eo, 180 long long eo,
diff --git a/src/nissy.h b/src/nissy.h
index 38fe656..959b2d8 100644
--- a/src/nissy.h
+++ b/src/nissy.h
@@ -27,6 +27,7 @@ for example 'rotation UF' or 'mirrored BL'.
27#define NISSY_SIZE_TRANSFORMATION 12U 27#define NISSY_SIZE_TRANSFORMATION 12U
28#define NISSY_SIZE_SOLVE_STATS 10U 28#define NISSY_SIZE_SOLVE_STATS 10U
29#define NISSY_SIZE_DATAID 255U 29#define NISSY_SIZE_DATAID 255U
30#define NISSY_SIZE_MOVES 1000U
30 31
31/* Flags for NISS options */ 32/* Flags for NISS options */
32#define NISSY_NISSFLAG_NORMAL 1U 33#define NISSY_NISSFLAG_NORMAL 1U
@@ -99,6 +100,12 @@ not known.
99#define NISSY_ERROR_INVALID_SOLVER -50LL 100#define NISSY_ERROR_INVALID_SOLVER -50LL
100 101
101/* 102/*
103The value NISSY_ERROR_INVALID_VARIATION means that the given method of
104finding variations for a solution is not known.
105*/
106#define NISSY_ERROR_INVALID_VARIATION -51LL
107
108/*
102The value NISSY_ERROR_NULL_POINTER means that one of the provided pointer 109The value NISSY_ERROR_NULL_POINTER means that one of the provided pointer
103arguments is NULL. For example, it may be returned by solve when called 110arguments is NULL. For example, it may be returned by solve when called
104with a solver that requires some pre-computed data, but the provided 111with a solver that requires some pre-computed data, but the provided
@@ -205,6 +212,36 @@ nissy_applytrans(
205); 212);
206 213
207/* 214/*
215Find variations of a given move sequence, for example by changing
216the direction of the last quarter turn(s), or linearizing a NISS move
217sequence. The result consists of one or more move sequences, one per line,
218and it always ends in a newline character.
219
220Parameters:
221 moves - The moves of which to find the variation. Must be at most
222 NISSY_SIZE_MOVES long.
223 variations - Specify which kind of variations to find, e.g. "lastqt".
224 result_size - The size of the result buffer.
225 result - The result buffer.
226
227Return values:
228 NISSY_ERROR_NULL_POINTER - One of the provided pointers is NULL.
229 NISSY_ERROR_INVALID_MOVES - The given moves are invalid.
230 NISSY_ERROR_INVALID_VARIATION - The given transformer is not known.
231 NISSY_ERROR_BUFFER_SIZE - Either the result buffer is too small or the
232 given move sequence is longer than
233 NISSY_SIZE_MOVES.
234 Any value >= 0 - The number of variations found.
235*/
236long long
237nissy_variations(
238 const char *moves,
239 const char *variation,
240 unsigned long long result_size,
241 char *result
242);
243
244/*
208Get the cube with the given ep, eo, cp and co values. The values must be in the 245Get the cube with the given ep, eo, cp and co values. The values must be in the
209ranges specified below, but if the option "fix" is given any values outside its 246ranges specified below, but if the option "fix" is given any values outside its
210range will be adjusted before using it. The option "fix" also fixes parity and 247range will be adjusted before using it. The option "fix" also fixes parity and
@@ -365,6 +402,8 @@ nissy_solve(
365); 402);
366 403
367/* 404/*
405Count the given moves.
406
368Parameters: 407Parameters:
369 moves - The moves to be counted. 408 moves - The moves to be counted.
370 409
@@ -379,6 +418,8 @@ nissy_countmoves(
379); 418);
380 419
381/* 420/*
421Compare the two moves sequences. Both must be at most NISSY_SIZE_MOVES long.
422
382Parameters: 423Parameters:
383 moves1 - The first sequence of moves to compare. 424 moves1 - The first sequence of moves to compare.
384 moves2 - The second sequence of moves to compare. 425 moves2 - The second sequence of moves to compare.
diff --git a/src/solvers/solutions.h b/src/solvers/solutions.h
index 00ed84c..9f209d1 100644
--- a/src/solvers/solutions.h
+++ b/src/solvers/solutions.h
@@ -55,7 +55,7 @@ solution_list_init(solution_list_t sols[static 1], size_t n, char *buf)
55 return false; 55 return false;
56 56
57 sols->nsols = 0; 57 sols->nsols = 0;
58 sols->shortest_sol = MAXLEN + 1; 58 sols->shortest_sol = SOLUTION_MAXLEN + 1;
59 sols->size = n; 59 sols->size = n;
60 sols->used = 0; 60 sols->used = 0;
61 sols->buf = buf; 61 sols->buf = buf;
@@ -162,7 +162,7 @@ appendsolution(
162 uint8_t t; 162 uint8_t t;
163 solution_moves_t tsol[NTRANS]; 163 solution_moves_t tsol[NTRANS];
164 164
165 if (moves->nmoves + moves->npremoves > MAXLEN) 165 if (moves->nmoves + moves->npremoves > SOLUTION_MAXLEN)
166 goto appendsolution_error_solution_length; 166 goto appendsolution_error_solution_length;
167 167
168 for ( 168 for (
diff --git a/src/solvers/solutions_types_macros.h b/src/solvers/solutions_types_macros.h
index f1cb517..e57e039 100644
--- a/src/solvers/solutions_types_macros.h
+++ b/src/solvers/solutions_types_macros.h
@@ -1,10 +1,10 @@
1#define MAXLEN 20 1#define SOLUTION_MAXLEN 20
2 2
3typedef struct { 3typedef struct {
4 uint8_t nmoves; 4 uint8_t nmoves;
5 uint8_t moves[MAXLEN]; 5 uint8_t moves[SOLUTION_MAXLEN];
6 uint8_t npremoves; 6 uint8_t npremoves;
7 uint8_t premoves[MAXLEN]; 7 uint8_t premoves[SOLUTION_MAXLEN];
8} solution_moves_t; 8} solution_moves_t;
9 9
10typedef struct { 10typedef struct {

Generated with cgit - Back to sebastiano.tronto.net