aboutsummaryrefslogtreecommitdiff
path: root/src/core/cube.h
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2024-08-18 14:26:45 +0200
committerSebastiano Tronto <sebastiano@tronto.net>2024-08-18 14:26:45 +0200
commit18c9a8b8905304cf5f8fc15825769046a3144866 (patch)
treea7807bb32b0a5d9ded7d3cedccc598f64a9b00fe /src/core/cube.h
parentf25a10e19eca294c4e6a99e4f80ce5cfd11a0e5f (diff)
downloadnissy-core-18c9a8b8905304cf5f8fc15825769046a3144866.tar.gz
nissy-core-18c9a8b8905304cf5f8fc15825769046a3144866.zip
Reorganized folder structure
Diffstat (limited to 'src/core/cube.h')
-rw-r--r--src/core/cube.h291
1 files changed, 291 insertions, 0 deletions
diff --git a/src/core/cube.h b/src/core/cube.h
new file mode 100644
index 0000000..fe36f90
--- /dev/null
+++ b/src/core/cube.h
@@ -0,0 +1,291 @@
1#define _move(M, c) compose(c, _move_cube_ ## M)
2#define _premove(M, c) compose(_move_cube_ ## M, c)
3
4_static cube_t cubefromarray(uint8_t [static 8], uint8_t [static 12]);
5_static cube_t solvedcube(void);
6_static bool isconsistent(cube_t);
7_static bool issolvable(cube_t);
8_static bool issolved(cube_t);
9_static bool iserror(cube_t);
10_static cube_t applymoves(cube_t, const char *);
11_static cube_t applytrans(cube_t, const char *);
12_static cube_t frommoves(const char *);
13_static void getcube_fix(int64_t *, int64_t *, int64_t *, int64_t *);
14_static cube_t getcube(int64_t, int64_t, int64_t, int64_t);
15
16_static cube_t move(cube_t, uint8_t);
17_static cube_t transform_edges(cube_t, uint8_t);
18_static cube_t transform_corners(cube_t, uint8_t);
19_static cube_t transform(cube_t, uint8_t);
20
21_static cube_t
22cubefromarray(uint8_t c[static 8], uint8_t e[static 12])
23{
24 return static_cube(
25 c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7],
26 e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7],
27 e[8], e[9], e[10], e[11]);
28}
29
30_static cube_t
31solvedcube(void)
32{
33 return solved;
34}
35
36_static bool
37isconsistent(cube_t cube)
38{
39 uint8_t i, p, e, piece, corner[8], edge[12];
40 bool found[12];
41
42 pieces(&cube, corner, edge);
43
44 for (i = 0; i < 12; i++)
45 found[i] = false;
46 for (i = 0; i < 12; i++) {
47 piece = edge[i];
48 p = piece & _pbits;
49 e = piece & _eobit;
50 if (p >= 12)
51 goto inconsistent_ep;
52 if (e != 0 && e != _eobit)
53 goto inconsistent_eo;
54 found[p] = true;
55 }
56 for (i = 0; i < 12; i++)
57 if (!found[i])
58 goto inconsistent_ep;
59
60 for (i = 0; i < 8; i++)
61 found[i] = false;
62 for (i = 0; i < 8; i++) {
63 piece = corner[i];
64 p = piece & _pbits;
65 e = piece & _cobits;
66 if (p >= 8)
67 goto inconsistent_cp;
68 if (e != 0 && e != _ctwist_cw && e != _ctwist_ccw)
69 goto inconsistent_co;
70 found[p] = true;
71 }
72 for (i = 0; i < 8; i++)
73 if (!found[i])
74 goto inconsistent_co;
75
76 return true;
77
78inconsistent_ep:
79 LOG("Inconsistent EP\n");
80 return false;
81inconsistent_cp:
82 LOG("Inconsistent CP\n");
83 return false;
84inconsistent_eo:
85 LOG("Inconsistent EO\n");
86 return false;
87inconsistent_co:
88 LOG("Inconsistent CO\n");
89 return false;
90}
91
92_static bool
93issolvable(cube_t cube)
94{
95 uint8_t i, eo, co, piece, edge[12], corner[8], ep[12], cp[8];
96
97 DBG_ASSERT(isconsistent(cube), false,
98 "issolvable: cube is inconsistent\n");
99
100 pieces(&cube, corner, edge);
101 for (i = 0; i < 12; i++)
102 ep[i] = edge[i] & _pbits;
103 for (i = 0; i < 8; i++)
104 cp[i] = corner[i] & _pbits;
105
106 if (permsign(ep, 12) != permsign(cp, 8))
107 goto issolvable_parity;
108
109 eo = 0;
110 for (i = 0; i < 12; i++) {
111 piece = edge[i];
112 eo += (piece & _eobit) >> _eoshift;
113 }
114 if (eo % 2 != 0)
115 goto issolvable_eo;
116
117 co = 0;
118 for (i = 0; i < 8; i++) {
119 piece = corner[i];
120 co += (piece & _cobits) >> _coshift;
121 }
122 if (co % 3 != 0)
123 goto issolvable_co;
124
125 return true;
126
127issolvable_parity:
128 LOG("EP and CP parities are different\n");
129 return false;
130issolvable_eo:
131 LOG("Odd number of flipped edges\n");
132 return false;
133issolvable_co:
134 LOG("Sum of corner orientation is not multiple of 3\n");
135 return false;
136}
137
138bool
139issolved(cube_t cube)
140{
141 return equal(cube, solved);
142}
143
144bool
145iserror(cube_t cube)
146{
147 return equal(cube, zero);
148}
149
150_static cube_t
151applymoves(cube_t cube, const char *buf)
152{
153 uint8_t r, m;
154 const char *b;
155
156 DBG_ASSERT(isconsistent(cube), zero,
157 "move error: inconsistent cube\n");
158
159 for (b = buf; *b != '\0'; b++) {
160 while (*b == ' ' || *b == '\t' || *b == '\n')
161 b++;
162 if (*b == '\0')
163 goto applymoves_finish;
164 if ((r = readmove(*b)) == _error)
165 goto applymoves_error;
166 if ((m = readmodifier(*(b+1))) != 0)
167 b++;
168 cube = move(cube, r + m);
169 }
170
171applymoves_finish:
172 return cube;
173
174applymoves_error:
175 LOG("applymoves error\n");
176 return zero;
177}
178
179_static cube_t
180frommoves(const char *buf)
181{
182 return applymoves(solved, buf);
183}
184
185_static void
186getcube_fix(int64_t *ep, int64_t *eo, int64_t *cp, int64_t *co)
187{
188 uint8_t e[12], c[8], coarr[8];
189
190 *ep = (*ep % _12f + _12f) % _12f;
191 *eo = (*eo % _2p11 + _2p11) % _2p11;
192 *cp = (*cp % _8f + _8f) % _8f;
193 *co = (*cp % _3p7 + _3p7) % _3p7;
194
195 indextoperm(*ep, 12, e);
196 indextoperm(*cp, 8, c);
197 if (permsign(e, 12) != permsign(c, 8)) {
198 _swap(c[0], c[1]);
199 *cp = permtoindex(c, 8);
200
201 sumzerotodigits(*co, 8, 3, coarr);
202 _swap(coarr[0], coarr[1]);
203 *co = digitstosumzero(coarr, 8, 3);
204 }
205}
206
207_static cube_t
208getcube(int64_t ep, int64_t eo, int64_t cp, int64_t co)
209{
210 uint8_t i, earr[12], carr[8], eoarr[12], coarr[8];
211
212 sumzerotodigits(eo, 12, 2, eoarr);
213 DBG_ASSERT(eoarr[0] != _error, zero, "Error making EO");
214 indextoperm(ep, 12, earr);
215 DBG_ASSERT(earr[0] != _error, zero, "Error making EP");
216 for (i = 0; i < 12; i++)
217 earr[i] |= eoarr[i] << _eoshift;
218
219 sumzerotodigits(co, 8, 3, coarr);
220 DBG_ASSERT(coarr[0] != _error, zero, "Error making CO");
221 indextoperm(cp, 8, carr);
222 DBG_ASSERT(carr[0] != _error, zero, "Error making CP");
223 for (i = 0; i < 8; i++)
224 carr[i] |= coarr[i] << _coshift;
225
226 return cubefromarray(carr, earr);
227}
228
229_static cube_t
230applytrans(cube_t cube, const char *buf)
231{
232 uint8_t t;
233
234 DBG_ASSERT(isconsistent(cube), zero,
235 "transformation error: inconsistent cube\n");
236
237 t = readtrans(buf);
238
239 return transform(cube, t);
240}
241
242_static cube_t
243move(cube_t c, uint8_t m)
244{
245 switch (m) {
246 case _move_U:
247 return _move(U, c);
248 case _move_U2:
249 return _move(U2, c);
250 case _move_U3:
251 return _move(U3, c);
252 case _move_D:
253 return _move(D, c);
254 case _move_D2:
255 return _move(D2, c);
256 case _move_D3:
257 return _move(D3, c);
258 case _move_R:
259 return _move(R, c);
260 case _move_R2:
261 return _move(R2, c);
262 case _move_R3:
263 return _move(R3, c);
264 case _move_L:
265 return _move(L, c);
266 case _move_L2:
267 return _move(L2, c);
268 case _move_L3:
269 return _move(L3, c);
270 case _move_F:
271 return _move(F, c);
272 case _move_F2:
273 return _move(F2, c);
274 case _move_F3:
275 return _move(F3, c);
276 case _move_B:
277 return _move(B, c);
278 case _move_B2:
279 return _move(B2, c);
280 case _move_B3:
281 return _move(B3, c);
282 default:
283 LOG("move error, unknown move\n");
284 return zero;
285 }
286}
287
288/*
289TODO transform is now relegated to a separated file because it is too long.
290It would be nice to make it shorter without loosing performance.
291*/

Generated with cgit - Back to sebastiano.tronto.net