diff options
| author | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2021-11-11 21:37:34 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2021-11-11 21:37:34 +0100 |
| commit | 3568412f8f230774d0d11d7ed1c897424f95d3ef (patch) | |
| tree | 77223792d8c925a9b1fc32b3f4341e943b5f8209 /src/cube.c | |
| parent | 67e1b5e6e6a2c917a2fe58a37a1382c982b1e5c5 (diff) | |
| download | nissy-3568412f8f230774d0d11d7ed1c897424f95d3ef.tar.gz nissy-3568412f8f230774d0d11d7ed1c897424f95d3ef.zip | |
Rewritten from scratch. Welocme nissy 2.0!
Diffstat (limited to '')
| -rw-r--r-- | src/cube.c | 701 |
1 files changed, 701 insertions, 0 deletions
diff --git a/src/cube.c b/src/cube.c new file mode 100644 index 0000000..06c8b8c --- /dev/null +++ b/src/cube.c | |||
| @@ -0,0 +1,701 @@ | |||
| 1 | #include "cube.h" | ||
| 2 | |||
| 3 | /* Local functions **********************************************************/ | ||
| 4 | |||
| 5 | static int array_ep_to_epos(int *ep, int *eps_solved); | ||
| 6 | static int epos_from_arrays(int *epos, int *ep); | ||
| 7 | |||
| 8 | /* Local functions implementation ********************************************/ | ||
| 9 | |||
| 10 | static int | ||
| 11 | array_ep_to_epos(int *ep, int *ss) | ||
| 12 | { | ||
| 13 | int epos[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
| 14 | int eps[4]; | ||
| 15 | int i, j, is; | ||
| 16 | |||
| 17 | for (i = 0, is = 0; i < 12; i++) { | ||
| 18 | for (j = 0; j < 4; j++) { | ||
| 19 | if (ep[i] == ss[j]) { | ||
| 20 | eps[is++] = j; | ||
| 21 | epos[i] = 1; | ||
| 22 | } | ||
| 23 | } | ||
| 24 | } | ||
| 25 | |||
| 26 | for (i = 0; i < 4; i++) | ||
| 27 | swap(&epos[ss[i]], &epos[i+8]); | ||
| 28 | |||
| 29 | return epos_from_arrays(epos, eps); | ||
| 30 | } | ||
| 31 | |||
| 32 | static int | ||
| 33 | epos_from_arrays(int *epos, int *ep) | ||
| 34 | { | ||
| 35 | return FACTORIAL4 * subset_to_index(epos,12,4) + perm_to_index(ep,4); | ||
| 36 | } | ||
| 37 | |||
| 38 | /* Public functions implementation *******************************************/ | ||
| 39 | |||
| 40 | Cube | ||
| 41 | arrays_to_cube(CubeArray *arr, PieceFilter f) | ||
| 42 | { | ||
| 43 | Cube ret = {0}; | ||
| 44 | |||
| 45 | static int epe_solved[4] = {FR, FL, BL, BR}; | ||
| 46 | static int eps_solved[4] = {UL, UR, DL, DR}; | ||
| 47 | static int epm_solved[4] = {UF, UB, DF, DB}; | ||
| 48 | |||
| 49 | if (f.epose) | ||
| 50 | ret.epose = array_ep_to_epos(arr->ep, epe_solved); | ||
| 51 | if (f.eposs) | ||
| 52 | ret.eposs = array_ep_to_epos(arr->ep, eps_solved); | ||
| 53 | if (f.eposm) | ||
| 54 | ret.eposm = array_ep_to_epos(arr->ep, epm_solved); | ||
| 55 | if (f.eofb) | ||
| 56 | ret.eofb = digit_array_to_int(arr->eofb, 11, 2); | ||
| 57 | if (f.eorl) | ||
| 58 | ret.eorl = digit_array_to_int(arr->eorl, 11, 2); | ||
| 59 | if (f.eoud) | ||
| 60 | ret.eoud = digit_array_to_int(arr->eoud, 11, 2); | ||
| 61 | if (f.cp) | ||
| 62 | ret.cp = perm_to_index(arr->cp, 8); | ||
| 63 | if (f.coud) | ||
| 64 | ret.coud = digit_array_to_int(arr->coud, 7, 3); | ||
| 65 | if (f.corl) | ||
| 66 | ret.corl = digit_array_to_int(arr->corl, 7, 3); | ||
| 67 | if (f.cofb) | ||
| 68 | ret.cofb = digit_array_to_int(arr->cofb, 7, 3); | ||
| 69 | if (f.cpos) | ||
| 70 | ret.cpos = perm_to_index(arr->cpos, 6); | ||
| 71 | |||
| 72 | return ret; | ||
| 73 | } | ||
| 74 | |||
| 75 | Cube | ||
| 76 | compose_filtered(Cube c2, Cube c1, PieceFilter f) | ||
| 77 | { | ||
| 78 | CubeArray *arr = new_cubearray(c2, f); | ||
| 79 | Cube ret; | ||
| 80 | |||
| 81 | ret = move_via_arrays(arr, c1, f); | ||
| 82 | free_cubearray(arr, f); | ||
| 83 | |||
| 84 | return ret; | ||
| 85 | } | ||
| 86 | |||
| 87 | void | ||
| 88 | cube_to_arrays(Cube cube, CubeArray *arr, PieceFilter f) | ||
| 89 | { | ||
| 90 | int i; | ||
| 91 | |||
| 92 | static int epe_solved[4] = {FR, FL, BL, BR}; | ||
| 93 | static int eps_solved[4] = {UL, UR, DL, DR}; | ||
| 94 | static int epm_solved[4] = {UF, UB, DF, DB}; | ||
| 95 | |||
| 96 | if (f.epose || f.eposs || f.eposm) | ||
| 97 | for (i = 0; i < 12; i++) | ||
| 98 | arr->ep[i] = -1; | ||
| 99 | |||
| 100 | if (f.epose) | ||
| 101 | epos_to_partial_ep(cube.epose, arr->ep, epe_solved); | ||
| 102 | if (f.eposs) | ||
| 103 | epos_to_partial_ep(cube.eposs, arr->ep, eps_solved); | ||
| 104 | if (f.eposm) | ||
| 105 | epos_to_partial_ep(cube.eposm, arr->ep, epm_solved); | ||
| 106 | if (f.eofb) | ||
| 107 | int_to_sum_zero_array(cube.eofb, 2, 12, arr->eofb); | ||
| 108 | if (f.eorl) | ||
| 109 | int_to_sum_zero_array(cube.eorl, 2, 12, arr->eorl); | ||
| 110 | if (f.eoud) | ||
| 111 | int_to_sum_zero_array(cube.eoud, 2, 12, arr->eoud); | ||
| 112 | if (f.cp) | ||
| 113 | index_to_perm(cube.cp, 8, arr->cp); | ||
| 114 | if (f.coud) | ||
| 115 | int_to_sum_zero_array(cube.coud, 3, 8, arr->coud); | ||
| 116 | if (f.corl) | ||
| 117 | int_to_sum_zero_array(cube.corl, 3, 8, arr->corl); | ||
| 118 | if (f.cofb) | ||
| 119 | int_to_sum_zero_array(cube.cofb, 3, 8, arr->cofb); | ||
| 120 | if (f.cpos) | ||
| 121 | index_to_perm(cube.cpos, 6, arr->cpos); | ||
| 122 | } | ||
| 123 | |||
| 124 | void | ||
| 125 | epos_to_partial_ep(int epos, int *ep, int *ss) | ||
| 126 | { | ||
| 127 | int i, is, eposs[12], eps[4]; | ||
| 128 | |||
| 129 | index_to_perm(epos % FACTORIAL4, 4, eps); | ||
| 130 | index_to_subset(epos / FACTORIAL4, 12, 4, eposs); | ||
| 131 | |||
| 132 | for (i = 0; i < 4; i++) | ||
| 133 | swap(&eposs[ss[i]], &eposs[i+8]); | ||
| 134 | |||
| 135 | for (i = 0, is = 0; i < 12; i++) | ||
| 136 | if (eposs[i]) | ||
| 137 | ep[i] = ss[eps[is++]]; | ||
| 138 | } | ||
| 139 | |||
| 140 | void | ||
| 141 | free_cubearray(CubeArray *arr, PieceFilter f) | ||
| 142 | { | ||
| 143 | if (f.epose || f.eposs || f.eposm) | ||
| 144 | free(arr->ep); | ||
| 145 | if (f.eofb) | ||
| 146 | free(arr->eofb); | ||
| 147 | if (f.eorl) | ||
| 148 | free(arr->eorl); | ||
| 149 | if (f.eoud) | ||
| 150 | free(arr->eoud); | ||
| 151 | if (f.cp) | ||
| 152 | free(arr->cp); | ||
| 153 | if (f.coud) | ||
| 154 | free(arr->coud); | ||
| 155 | if (f.corl) | ||
| 156 | free(arr->corl); | ||
| 157 | if (f.cofb) | ||
| 158 | free(arr->cofb); | ||
| 159 | if (f.cpos) | ||
| 160 | free(arr->cpos); | ||
| 161 | |||
| 162 | free(arr); | ||
| 163 | } | ||
| 164 | |||
| 165 | Cube | ||
| 166 | move_via_arrays(CubeArray *arr, Cube c, PieceFilter f) | ||
| 167 | { | ||
| 168 | CubeArray *arrc = new_cubearray(c, f); | ||
| 169 | Cube ret; | ||
| 170 | |||
| 171 | if (f.epose || f.eposs || f.eposm) | ||
| 172 | apply_permutation(arr->ep, arrc->ep, 12); | ||
| 173 | |||
| 174 | if (f.eofb) { | ||
| 175 | apply_permutation(arr->ep, arrc->eofb, 12); | ||
| 176 | sum_arrays_mod(arr->eofb, arrc->eofb, 12, 2); | ||
| 177 | } | ||
| 178 | |||
| 179 | if (f.eorl) { | ||
| 180 | apply_permutation(arr->ep, arrc->eorl, 12); | ||
| 181 | sum_arrays_mod(arr->eorl, arrc->eorl, 12, 2); | ||
| 182 | } | ||
| 183 | |||
| 184 | if (f.eoud) { | ||
| 185 | apply_permutation(arr->ep, arrc->eoud, 12); | ||
| 186 | sum_arrays_mod(arr->eoud, arrc->eoud, 12, 2); | ||
| 187 | } | ||
| 188 | |||
| 189 | if (f.cp) | ||
| 190 | apply_permutation(arr->cp, arrc->cp, 8); | ||
| 191 | |||
| 192 | if (f.coud) { | ||
| 193 | apply_permutation(arr->cp, arrc->coud, 8); | ||
| 194 | sum_arrays_mod(arr->coud, arrc->coud, 8, 3); | ||
| 195 | } | ||
| 196 | |||
| 197 | if (f.corl) { | ||
| 198 | apply_permutation(arr->cp, arrc->corl, 8); | ||
| 199 | sum_arrays_mod(arr->corl, arrc->corl, 8, 3); | ||
| 200 | } | ||
| 201 | |||
| 202 | if (f.cofb) { | ||
| 203 | apply_permutation(arr->cp, arrc->cofb, 8); | ||
| 204 | sum_arrays_mod(arr->cofb, arrc->cofb, 8, 3); | ||
| 205 | } | ||
| 206 | |||
| 207 | if (f.cpos) | ||
| 208 | apply_permutation(arr->cpos, arrc->cpos, 6); | ||
| 209 | |||
| 210 | ret = arrays_to_cube(arrc, f); | ||
| 211 | free_cubearray(arrc, f); | ||
| 212 | |||
| 213 | return ret; | ||
| 214 | } | ||
| 215 | |||
| 216 | CubeArray * | ||
| 217 | new_cubearray(Cube cube, PieceFilter f) | ||
| 218 | { | ||
| 219 | CubeArray *arr = malloc(sizeof(CubeArray)); | ||
| 220 | |||
| 221 | if (f.epose || f.eposs || f.eposm) | ||
| 222 | arr->ep = malloc(12 * sizeof(int)); | ||
| 223 | if (f.eofb) | ||
| 224 | arr->eofb = malloc(12 * sizeof(int)); | ||
| 225 | if (f.eorl) | ||
| 226 | arr->eorl = malloc(12 * sizeof(int)); | ||
| 227 | if (f.eoud) | ||
| 228 | arr->eoud = malloc(12 * sizeof(int)); | ||
| 229 | if (f.cp) | ||
| 230 | arr->cp = malloc(8 * sizeof(int)); | ||
| 231 | if (f.coud) | ||
| 232 | arr->coud = malloc(8 * sizeof(int)); | ||
| 233 | if (f.corl) | ||
| 234 | arr->corl = malloc(8 * sizeof(int)); | ||
| 235 | if (f.cofb) | ||
| 236 | arr->cofb = malloc(8 * sizeof(int)); | ||
| 237 | if (f.cpos) | ||
| 238 | arr->cpos = malloc(6 * sizeof(int)); | ||
| 239 | |||
| 240 | cube_to_arrays(cube, arr, f); | ||
| 241 | |||
| 242 | return arr; | ||
| 243 | } | ||
| 244 | |||
| 245 | Cube | ||
| 246 | admissible_ep(Cube cube, PieceFilter f) | ||
| 247 | { | ||
| 248 | CubeArray *arr = new_cubearray(cube, f); | ||
| 249 | Cube ret; | ||
| 250 | bool used[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 251 | int i, j; | ||
| 252 | |||
| 253 | for (i = 0; i < 12; i++) | ||
| 254 | if (arr->ep[i] != -1) | ||
| 255 | used[arr->ep[i]] = true; | ||
| 256 | |||
| 257 | for (i = 0, j = 0; i < 12; i++) { | ||
| 258 | for ( ; j < 11 && used[j]; j++); | ||
| 259 | if (arr->ep[i] == -1) | ||
| 260 | arr->ep[i] = j++; | ||
| 261 | } | ||
| 262 | |||
| 263 | ret = arrays_to_cube(arr, pf_ep); | ||
| 264 | free_cubearray(arr, f); | ||
| 265 | |||
| 266 | return ret; | ||
| 267 | } | ||
| 268 | |||
| 269 | Cube | ||
| 270 | compose(Cube c2, Cube c1) | ||
| 271 | { | ||
| 272 | return compose_filtered(c2, c1, pf_all); | ||
| 273 | } | ||
| 274 | |||
| 275 | int | ||
| 276 | edge_slice(Edge e) { | ||
| 277 | if (e < 0 || e > 11) | ||
| 278 | return -1; | ||
| 279 | |||
| 280 | if (e == FR || e == FL || e == BL || e == BR) | ||
| 281 | return 0; | ||
| 282 | if (e == UR || e == UL || e == DR || e == DL) | ||
| 283 | return 1; | ||
| 284 | |||
| 285 | return 2; | ||
| 286 | } | ||
| 287 | |||
| 288 | bool | ||
| 289 | equal(Cube c1, Cube c2) | ||
| 290 | { | ||
| 291 | return c1.eofb == c2.eofb && | ||
| 292 | c1.epose == c2.epose && | ||
| 293 | c1.eposs == c2.eposs && | ||
| 294 | c1.eposm == c2.eposm && | ||
| 295 | c1.coud == c2.coud && | ||
| 296 | c1.cp == c2.cp && | ||
| 297 | c1.cpos == c2.cpos; | ||
| 298 | } | ||
| 299 | |||
| 300 | Cube | ||
| 301 | inverse_cube(Cube cube) | ||
| 302 | { | ||
| 303 | CubeArray *arr = new_cubearray(cube, pf_all); | ||
| 304 | CubeArray *inv = new_cubearray((Cube){0}, pf_all); | ||
| 305 | Cube ret; | ||
| 306 | int i; | ||
| 307 | |||
| 308 | for (i = 0; i < 12; i++) { | ||
| 309 | inv->ep[arr->ep[i]] = i; | ||
| 310 | inv->eofb[arr->ep[i]] = arr->eofb[i]; | ||
| 311 | inv->eorl[arr->ep[i]] = arr->eorl[i]; | ||
| 312 | inv->eoud[arr->ep[i]] = arr->eoud[i]; | ||
| 313 | } | ||
| 314 | |||
| 315 | for (i = 0; i < 8; i++) { | ||
| 316 | inv->cp[arr->cp[i]] = i; | ||
| 317 | inv->coud[arr->cp[i]] = (3 - arr->coud[i]) % 3; | ||
| 318 | inv->corl[arr->cp[i]] = (3 - arr->corl[i]) % 3; | ||
| 319 | inv->cofb[arr->cp[i]] = (3 - arr->cofb[i]) % 3; | ||
| 320 | } | ||
| 321 | |||
| 322 | for (int i = 0; i < 6; i++) | ||
| 323 | inv->cpos[arr->cpos[i]] = i; | ||
| 324 | |||
| 325 | ret = arrays_to_cube(inv, pf_all); | ||
| 326 | free_cubearray(arr, pf_all); | ||
| 327 | free_cubearray(inv, pf_all); | ||
| 328 | |||
| 329 | return ret; | ||
| 330 | } | ||
| 331 | |||
| 332 | bool | ||
| 333 | is_admissible(Cube cube) | ||
| 334 | { | ||
| 335 | /* TODO: this should check consistency of different orientations */ | ||
| 336 | /* check also that centers are opposite and admissible */ | ||
| 337 | |||
| 338 | CubeArray *a = new_cubearray(cube, pf_all); | ||
| 339 | int parity; | ||
| 340 | bool perm; | ||
| 341 | |||
| 342 | perm = is_perm(a->ep, 12) && | ||
| 343 | is_perm(a->cp, 8) && | ||
| 344 | is_perm(a->cpos, 6); | ||
| 345 | parity = perm_sign(a->ep, 12) + | ||
| 346 | perm_sign(a->cp, 8) + | ||
| 347 | perm_sign(a->cpos, 6); | ||
| 348 | |||
| 349 | return perm && parity % 2 == 0; | ||
| 350 | } | ||
| 351 | |||
| 352 | bool | ||
| 353 | is_solved(Cube cube) | ||
| 354 | { | ||
| 355 | return equal(cube, (Cube){0}); | ||
| 356 | } | ||
| 357 | |||
| 358 | bool | ||
| 359 | is_block_solved(Cube cube, Block block) | ||
| 360 | { | ||
| 361 | int i; | ||
| 362 | |||
| 363 | for (i = 0; i < 12; i++) | ||
| 364 | if (block.edge[i] && !is_solved_edge(cube, i)) | ||
| 365 | return false; | ||
| 366 | for (i = 0; i < 8; i++) | ||
| 367 | if (block.corner[i] && !is_solved_corner(cube, i)) | ||
| 368 | return false; | ||
| 369 | for (i = 0; i < 6; i++) | ||
| 370 | if (block.center[i] && !is_solved_center(cube, i)) | ||
| 371 | return false; | ||
| 372 | |||
| 373 | return true; | ||
| 374 | } | ||
| 375 | |||
| 376 | bool | ||
| 377 | is_solved_center(Cube cube, Center c) | ||
| 378 | { | ||
| 379 | return what_center_at(cube, c) == c; | ||
| 380 | } | ||
| 381 | |||
| 382 | bool | ||
| 383 | is_solved_corner(Cube cube, Corner c) | ||
| 384 | { | ||
| 385 | return what_corner_at(cube, c) == c && | ||
| 386 | what_orientation_corner(cube.coud, c); | ||
| 387 | } | ||
| 388 | |||
| 389 | bool | ||
| 390 | is_solved_edge(Cube cube, Edge e) | ||
| 391 | { | ||
| 392 | return what_edge_at(cube, e) == e && | ||
| 393 | what_orientation_edge(cube.eofb, e); | ||
| 394 | } | ||
| 395 | |||
| 396 | int | ||
| 397 | piece_orientation(Cube cube, int piece, char *orientation) | ||
| 398 | { | ||
| 399 | int arr[12], n, b, x; | ||
| 400 | |||
| 401 | if (!strcmp(orientation, "eofb")) { | ||
| 402 | x = cube.eofb; | ||
| 403 | n = 12; | ||
| 404 | b = 2; | ||
| 405 | } else if (!strcmp(orientation, "eorl")) { | ||
| 406 | x = cube.eorl; | ||
| 407 | n = 12; | ||
| 408 | b = 2; | ||
| 409 | } else if (!strcmp(orientation, "eoud")) { | ||
| 410 | x = cube.eoud; | ||
| 411 | n = 12; | ||
| 412 | b = 2; | ||
| 413 | } else if (!strcmp(orientation, "coud")) { | ||
| 414 | x = cube.coud; | ||
| 415 | n = 8; | ||
| 416 | b = 3; | ||
| 417 | } else if (!strcmp(orientation, "corl")) { | ||
| 418 | x = cube.corl; | ||
| 419 | n = 8; | ||
| 420 | b = 3; | ||
| 421 | } else if (!strcmp(orientation, "cofb")) { | ||
| 422 | x = cube.cofb; | ||
| 423 | n = 8; | ||
| 424 | b = 3; | ||
| 425 | } else { | ||
| 426 | return -1; | ||
| 427 | } | ||
| 428 | |||
| 429 | int_to_sum_zero_array(x, b, n, arr); | ||
| 430 | if (piece < n) | ||
| 431 | return arr[piece]; | ||
| 432 | |||
| 433 | return -1; | ||
| 434 | } | ||
| 435 | |||
| 436 | void | ||
| 437 | print_cube(Cube cube) | ||
| 438 | { | ||
| 439 | static char edge_string[12][7] = { | ||
| 440 | [UF] = "UF", [UL] = "UL", [UB] = "UB", [UR] = "UR", | ||
| 441 | [DF] = "DF", [DL] = "DL", [DB] = "DB", [DR] = "DR", | ||
| 442 | [FR] = "FR", [FL] = "FL", [BL] = "BL", [BR] = "BR" | ||
| 443 | }; | ||
| 444 | |||
| 445 | static char corner_string[8][7] = { | ||
| 446 | [UFR] = "UFR", [UFL] = "UFL", [UBL] = "UBL", [UBR] = "UBR", | ||
| 447 | [DFR] = "DFR", [DFL] = "DFL", [DBL] = "DBL", [DBR] = "DBR" | ||
| 448 | }; | ||
| 449 | |||
| 450 | static char center_string[6][7] = { | ||
| 451 | [U_center] = "U", [D_center] = "D", | ||
| 452 | [R_center] = "R", [L_center] = "L", | ||
| 453 | [F_center] = "F", [B_center] = "B" | ||
| 454 | }; | ||
| 455 | |||
| 456 | for (int i = 0; i < 12; i++) | ||
| 457 | printf(" %s ", edge_string[what_edge_at(cube, i)]); | ||
| 458 | printf("\n"); | ||
| 459 | |||
| 460 | for (int i = 0; i < 12; i++) | ||
| 461 | printf(" %d ", what_orientation_edge(cube.eofb, i)); | ||
| 462 | printf("\n"); | ||
| 463 | |||
| 464 | for (int i = 0; i < 8; i++) | ||
| 465 | printf("%s ", corner_string[what_corner_at(cube, i)]); | ||
| 466 | printf("\n"); | ||
| 467 | |||
| 468 | for (int i = 0; i < 8; i++) | ||
| 469 | printf(" %d ", what_orientation_corner(cube.coud, i)); | ||
| 470 | printf("\n"); | ||
| 471 | |||
| 472 | for (int i = 0; i < 6; i++) | ||
| 473 | printf(" %s ", center_string[what_center_at(cube, i)]); | ||
| 474 | printf("\n"); | ||
| 475 | } | ||
| 476 | |||
| 477 | Cube | ||
| 478 | random_cube() | ||
| 479 | { | ||
| 480 | CubeArray *arr = new_cubearray((Cube){0}, pf_4val); | ||
| 481 | Cube ret; | ||
| 482 | int ep, cp, eo, co; | ||
| 483 | |||
| 484 | ep = rand() % FACTORIAL12; | ||
| 485 | cp = rand() % FACTORIAL8; | ||
| 486 | eo = rand() % POW2TO11; | ||
| 487 | co = rand() % POW3TO7; | ||
| 488 | |||
| 489 | index_to_perm(ep, 12, arr->ep); | ||
| 490 | index_to_perm(cp, 8, arr->cp); | ||
| 491 | int_to_sum_zero_array(eo, 2, 12, arr->eofb); | ||
| 492 | int_to_sum_zero_array(co, 3, 8, arr->coud); | ||
| 493 | |||
| 494 | if (perm_sign(arr->ep, 12) != perm_sign(arr->cp, 8)) | ||
| 495 | swap(&(arr->ep[0]), &(arr->ep[1])); | ||
| 496 | |||
| 497 | ret = arrays_to_cube(arr, pf_4val); | ||
| 498 | free_cubearray(arr, pf_4val); | ||
| 499 | |||
| 500 | return ret; | ||
| 501 | } | ||
| 502 | |||
| 503 | Center | ||
| 504 | what_center_at(Cube cube, Center c) | ||
| 505 | { | ||
| 506 | static bool initialized = false; | ||
| 507 | static Center aux[FACTORIAL6][6]; | ||
| 508 | static int i; | ||
| 509 | static unsigned int ui; | ||
| 510 | static CubeArray *arr; | ||
| 511 | |||
| 512 | if (!initialized) { | ||
| 513 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 514 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 515 | for (i = 0; i < 6; i++) | ||
| 516 | aux[ui][i] = arr->cpos[i]; | ||
| 517 | free_cubearray(arr, pf_cpos); | ||
| 518 | } | ||
| 519 | |||
| 520 | initialized = true; | ||
| 521 | } | ||
| 522 | |||
| 523 | return aux[cube.cpos][c]; | ||
| 524 | } | ||
| 525 | |||
| 526 | Corner | ||
| 527 | what_corner_at(Cube cube, Corner c) | ||
| 528 | { | ||
| 529 | static bool initialized = false; | ||
| 530 | static Corner aux[FACTORIAL8][8]; | ||
| 531 | static int i; | ||
| 532 | static unsigned int ui; | ||
| 533 | static CubeArray *arr; | ||
| 534 | |||
| 535 | if (!initialized) { | ||
| 536 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 537 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 538 | for (i = 0; i < 8; i++) | ||
| 539 | aux[ui][i] = arr->cp[i]; | ||
| 540 | free_cubearray(arr, pf_cp); | ||
| 541 | } | ||
| 542 | |||
| 543 | initialized = true; | ||
| 544 | } | ||
| 545 | |||
| 546 | return aux[cube.cp][c]; | ||
| 547 | } | ||
| 548 | |||
| 549 | Edge | ||
| 550 | what_edge_at(Cube cube, Edge e) | ||
| 551 | { | ||
| 552 | Edge ret; | ||
| 553 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 554 | |||
| 555 | ret = arr->ep[e]; | ||
| 556 | |||
| 557 | free_cubearray(arr, pf_ep); | ||
| 558 | return ret; | ||
| 559 | } | ||
| 560 | |||
| 561 | int | ||
| 562 | what_orientation_corner(int co, Corner c) | ||
| 563 | { | ||
| 564 | static bool initialized = false; | ||
| 565 | static int auxlast[POW3TO7]; | ||
| 566 | static int auxarr[8]; | ||
| 567 | static unsigned int ui; | ||
| 568 | |||
| 569 | if (!initialized) { | ||
| 570 | for (ui = 0; ui < POW3TO7; ui++) { | ||
| 571 | int_to_sum_zero_array(ui, 3, 8, auxarr); | ||
| 572 | auxlast[ui] = auxarr[7]; | ||
| 573 | } | ||
| 574 | |||
| 575 | initialized = true; | ||
| 576 | } | ||
| 577 | |||
| 578 | if (c < 7) | ||
| 579 | return (co / powint(3, c)) % 3; | ||
| 580 | else | ||
| 581 | return auxlast[co]; | ||
| 582 | } | ||
| 583 | |||
| 584 | int | ||
| 585 | what_orientation_edge(int eo, Edge e) | ||
| 586 | { | ||
| 587 | static bool initialized = false; | ||
| 588 | static int auxlast[POW2TO11]; | ||
| 589 | static int auxarr[12]; | ||
| 590 | static unsigned int ui; | ||
| 591 | |||
| 592 | if (!initialized) { | ||
| 593 | for (ui = 0; ui < POW2TO11; ui++) { | ||
| 594 | int_to_sum_zero_array(ui, 2, 12, auxarr); | ||
| 595 | auxlast[ui] = auxarr[11]; | ||
| 596 | } | ||
| 597 | |||
| 598 | initialized = true; | ||
| 599 | } | ||
| 600 | |||
| 601 | if (e < 11) | ||
| 602 | return (eo & (1 << e)) ? 1 : 0; | ||
| 603 | else | ||
| 604 | return auxlast[eo]; | ||
| 605 | } | ||
| 606 | |||
| 607 | Center | ||
| 608 | where_is_center(Cube cube, Center c) | ||
| 609 | { | ||
| 610 | static bool initialized = false; | ||
| 611 | static Center aux[FACTORIAL6][6]; | ||
| 612 | static int i; | ||
| 613 | static unsigned int ui; | ||
| 614 | static CubeArray *arr; | ||
| 615 | |||
| 616 | if (!initialized) { | ||
| 617 | for (ui = 0; ui < FACTORIAL6; ui++) { | ||
| 618 | arr = new_cubearray((Cube){.cpos = ui}, pf_cpos); | ||
| 619 | for (i = 0; i < 6; i++) | ||
| 620 | aux[ui][arr->cpos[i]] = i; | ||
| 621 | free_cubearray(arr, pf_cpos); | ||
| 622 | } | ||
| 623 | |||
| 624 | initialized = true; | ||
| 625 | } | ||
| 626 | |||
| 627 | return aux[cube.cpos][c]; | ||
| 628 | } | ||
| 629 | |||
| 630 | Corner | ||
| 631 | where_is_corner(Cube cube, Corner c) | ||
| 632 | { | ||
| 633 | static bool initialized = false; | ||
| 634 | static Corner aux[FACTORIAL8][8]; | ||
| 635 | static int i; | ||
| 636 | static unsigned int ui; | ||
| 637 | static CubeArray *arr; | ||
| 638 | |||
| 639 | if (!initialized) { | ||
| 640 | for (ui = 0; ui < FACTORIAL8; ui++) { | ||
| 641 | arr = new_cubearray((Cube){.cp = ui}, pf_cp); | ||
| 642 | for (i = 0; i < 8; i++) | ||
| 643 | aux[ui][arr->cp[i]] = i; | ||
| 644 | free_cubearray(arr, pf_cp); | ||
| 645 | } | ||
| 646 | |||
| 647 | initialized = true; | ||
| 648 | } | ||
| 649 | return aux[cube.cp][c]; | ||
| 650 | } | ||
| 651 | |||
| 652 | Edge | ||
| 653 | where_is_edge(Cube cube, Edge e) | ||
| 654 | { | ||
| 655 | /* TODO: when I wrote this code I forgot to add the final | ||
| 656 | part, and now I can't remember how it was supposed to | ||
| 657 | work (i.e. how to recover the location of the edge | ||
| 658 | from these tables. I think it is either very easy or | ||
| 659 | wrong, in any case it is not a priority now. | ||
| 660 | Future Seba can deal with it. | ||
| 661 | |||
| 662 | static bool initialized = false; | ||
| 663 | static Edge aux[3][FACTORIAL12/FACTORIAL8][12]; | ||
| 664 | static int i; | ||
| 665 | static unsigned int ui; | ||
| 666 | static CubeArray *arr; | ||
| 667 | |||
| 668 | if (!initialized) { | ||
| 669 | for (ui = 0; ui < FACTORIAL12/FACTORIAL8; ui++) { | ||
| 670 | arr = new_cubearray((Cube){.epose = ui}, pf_e); | ||
| 671 | for (i = 0; i < 12; i++) | ||
| 672 | if (edge_slice(arr->ep[i]) == 0) | ||
| 673 | aux[0][ui][arr->ep[i]] = i; | ||
| 674 | free_cubearray(arr, pf_e); | ||
| 675 | |||
| 676 | arr = new_cubearray((Cube){.eposs = ui}, pf_s); | ||
| 677 | for (i = 0; i < 12; i++) | ||
| 678 | if (edge_slice(arr->ep[i]) == 1) | ||
| 679 | aux[1][ui][arr->ep[i]] = i; | ||
| 680 | free_cubearray(arr, pf_s); | ||
| 681 | |||
| 682 | arr = new_cubearray((Cube){.eposm = ui}, pf_m); | ||
| 683 | for (i = 0; i < 12; i++) | ||
| 684 | if (edge_slice(arr->ep[i]) == 2) | ||
| 685 | aux[2][ui][arr->ep[i]] = i; | ||
| 686 | free_cubearray(arr, pf_m); | ||
| 687 | } | ||
| 688 | |||
| 689 | initialized = true; | ||
| 690 | } | ||
| 691 | */ | ||
| 692 | |||
| 693 | int i; | ||
| 694 | CubeArray *arr = new_cubearray(cube, pf_ep); | ||
| 695 | |||
| 696 | for (i = 0; i < 12; i++) | ||
| 697 | if ((Edge)arr->ep[i] == e) | ||
| 698 | return i; | ||
| 699 | |||
| 700 | return -1; | ||
| 701 | } | ||
