steps.c (36298B)
1 #include "steps.h" 2 3 #define UPDATECHECKSTOP(a, b, c) if ((a=(MAX((a),(b))))>(c)) return (a); 4 5 /* Checkers, estimators and validators ***************************************/ 6 7 static bool check_centers(Cube cube); 8 static bool check_coud_HTM(Cube cube); 9 static bool check_coud_URF(Cube cube); 10 static bool check_corners_HTM(Cube cube); 11 static bool check_corners_URF(Cube cube); 12 static bool check_cornershtr(Cube cube); 13 static bool check_eofb(Cube cube); 14 static bool check_drud(Cube cube); 15 static bool check_drud_or_drrl(Cube cube); 16 static bool check_htr(Cube cube); 17 static bool check_drudslice(Cube cube); 18 19 static int estimate_eofb_HTM(DfsArg *arg); 20 static int estimate_coud_HTM(DfsArg *arg); 21 static int estimate_coud_URF(DfsArg *arg); 22 static int estimate_corners_HTM(DfsArg *arg); 23 static int estimate_cornershtr_HTM(DfsArg *arg); 24 static int estimate_corners_URF(DfsArg *arg); 25 static int estimate_cornershtr_URF(DfsArg *arg); 26 static int estimate_drud_HTM(DfsArg *arg); 27 static int estimate_drud_eofb(DfsArg *arg); 28 static int estimate_dr_eofb(DfsArg *arg); 29 static int estimate_drudfin_drud(DfsArg *arg); 30 static int estimate_drudslice_drud(DfsArg *arg); 31 static int estimate_htr_drud(DfsArg *arg); 32 static int estimate_cp_drud(DfsArg *arg); 33 static int estimate_htrfin_htr(DfsArg *arg); 34 static int estimate_nxopt31_HTM(DfsArg *arg); 35 static int estimate_light_HTM(DfsArg *arg); 36 static int estimate_nxoptlike(DfsArg *arg, PruneData *pd); 37 38 static bool always_valid(Alg *alg); 39 static bool validate_singlecw_ending(Alg *alg); 40 static bool validate_htr(Alg *alg); 41 42 /* Pre-transformation detectors **********************************************/ 43 44 static int detect_pretrans_eofb(Cube cube, Trans *ret); 45 static int detect_pretrans_drud(Cube cube, Trans *ret); 46 static int detect_pretrans_void_3axis(Cube cube, Trans *ret); 47 48 /* Messages for when cube is not ready ***************************************/ 49 50 static char check_centers_msg[100] = "cube must be oriented (centers solved)"; 51 static char check_eo_msg[100] = "EO must be solved on given axis"; 52 static char check_dr_msg[100] = "DR must be solved on given axis"; 53 static char check_htr_msg[100] = "HTR must be solved"; 54 static char check_drany_msg[100] = "DR must be solved on at least one axis"; 55 static char check_co_msg[100] = "CO must be solved on the given axis"; 56 static char check_coany_msg[100] = "CO must be solved on at least one axis"; 57 58 /* Steps *********************************************************************/ 59 60 /* Optimal solvers *******************/ 61 62 Step 63 optimal_HTM = { 64 .shortname = "optimal", 65 .name = "Optimal solve (in HTM)", 66 67 .final = true, 68 .is_done = is_solved, 69 .estimate = estimate_nxopt31_HTM, 70 .ready = check_centers, 71 .ready_msg = check_centers_msg, 72 .is_valid = always_valid, 73 .moveset = &moveset_HTM, 74 75 .pre_trans = uf, 76 77 .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, 78 .ntables = 2, 79 }; 80 81 Step 82 optimal_light_HTM = { 83 .shortname = "light", 84 .name = "Optimal solve (in HTM), small table (500Mb RAM total)", 85 86 .final = true, 87 .is_done = is_solved, 88 .estimate = estimate_light_HTM, 89 .ready = check_centers, 90 .ready_msg = check_centers_msg, 91 .is_valid = always_valid, 92 .moveset = &moveset_HTM, 93 94 .pre_trans = uf, 95 96 .tables = {&pd_drud_sym16_HTM, &pd_corners_HTM}, 97 .ntables = 2, 98 }; 99 100 /* Optimal after EO ******************/ 101 102 Step 103 eofin_eo = { 104 .shortname = "eofin", 105 .name = "Optimal solve after EO without breaking EO (detected)", 106 107 .final = true, 108 .is_done = is_solved, 109 .estimate = estimate_nxopt31_HTM, 110 .ready = check_eofb, 111 .ready_msg = check_eo_msg, 112 .is_valid = always_valid, 113 .moveset = &moveset_eofb, 114 115 .detect = detect_pretrans_eofb, 116 117 .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, 118 .ntables = 2, 119 }; 120 121 Step 122 eofbfin_eofb = { 123 .shortname = "eofbfin", 124 .name = "Optimal after EO on F/B without breaking EO", 125 126 .final = true, 127 .is_done = is_solved, 128 .estimate = estimate_nxopt31_HTM, 129 .ready = check_eofb, 130 .ready_msg = check_eo_msg, 131 .is_valid = always_valid, 132 .moveset = &moveset_eofb, 133 134 .pre_trans = uf, 135 136 .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, 137 .ntables = 2, 138 }; 139 140 Step 141 eorlfin_eorl = { 142 .shortname = "eorlfin", 143 .name = "Optimal after EO on R/L without breaking EO", 144 145 .final = true, 146 .is_done = is_solved, 147 .estimate = estimate_nxopt31_HTM, 148 .ready = check_eofb, 149 .ready_msg = check_eo_msg, 150 .is_valid = always_valid, 151 .moveset = &moveset_eofb, 152 153 .pre_trans = ur, 154 155 .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, 156 .ntables = 2, 157 }; 158 159 Step 160 eoudfin_eoud = { 161 .shortname = "eoudfin", 162 .name = "Optimal after EO on U/D without breaking EO", 163 164 .final = true, 165 .is_done = is_solved, 166 .estimate = estimate_nxopt31_HTM, 167 .ready = check_eofb, 168 .ready_msg = check_eo_msg, 169 .is_valid = always_valid, 170 .moveset = &moveset_eofb, 171 172 .pre_trans = fd, 173 174 .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, 175 .ntables = 2, 176 }; 177 178 /* EO steps **************************/ 179 Step 180 eoany_HTM = { 181 .shortname = "eo", 182 .name = "EO on any axis", 183 184 .final = false, 185 .is_done = check_eofb, 186 .estimate = estimate_eofb_HTM, 187 .ready = check_centers, 188 .ready_msg = check_centers_msg, 189 .is_valid = validate_singlecw_ending, 190 .moveset = &moveset_HTM, 191 192 .detect = detect_pretrans_void_3axis, 193 194 .tables = {&pd_eofb_HTM}, 195 .ntables = 1, 196 }; 197 198 Step 199 eofb_HTM = { 200 .shortname = "eofb", 201 .name = "EO on F/B", 202 203 .final = false, 204 .is_done = check_eofb, 205 .estimate = estimate_eofb_HTM, 206 .ready = check_centers, 207 .ready_msg = check_centers_msg, 208 .is_valid = validate_singlecw_ending, 209 .moveset = &moveset_HTM, 210 211 .pre_trans = uf, 212 213 .tables = {&pd_eofb_HTM}, 214 .ntables = 1, 215 }; 216 217 Step 218 eorl_HTM = { 219 .shortname = "eorl", 220 .name = "EO on R/L", 221 222 .final = false, 223 .is_done = check_eofb, 224 .estimate = estimate_eofb_HTM, 225 .ready = check_centers, 226 .ready_msg = check_centers_msg, 227 .is_valid = validate_singlecw_ending, 228 .moveset = &moveset_HTM, 229 230 .pre_trans = ur, 231 232 .tables = {&pd_eofb_HTM}, 233 .ntables = 1, 234 }; 235 236 Step 237 eoud_HTM = { 238 .shortname = "eoud", 239 .name = "EO on U/D", 240 241 .final = false, 242 .is_done = check_eofb, 243 .estimate = estimate_eofb_HTM, 244 .ready = check_centers, 245 .ready_msg = check_centers_msg, 246 .is_valid = validate_singlecw_ending, 247 .moveset = &moveset_HTM, 248 249 .pre_trans = fd, 250 251 .tables = {&pd_eofb_HTM}, 252 .ntables = 1, 253 }; 254 255 /* CO steps **************************/ 256 Step 257 coany_HTM = { 258 .shortname = "co", 259 .name = "CO on any axis", 260 261 .final = false, 262 .is_done = check_coud_HTM, 263 .estimate = estimate_coud_HTM, 264 .ready = NULL, 265 .is_valid = validate_singlecw_ending, 266 .moveset = &moveset_HTM, 267 268 .detect = detect_pretrans_void_3axis, 269 270 .tables = {&pd_coud_HTM}, 271 .ntables = 1, 272 }; 273 274 Step 275 coud_HTM = { 276 .shortname = "coud", 277 .name = "CO on U/D", 278 279 .final = false, 280 .is_done = check_coud_HTM, 281 .estimate = estimate_coud_HTM, 282 .ready = NULL, 283 .is_valid = validate_singlecw_ending, 284 .moveset = &moveset_HTM, 285 286 .pre_trans = uf, 287 288 .tables = {&pd_coud_HTM}, 289 .ntables = 1, 290 }; 291 292 Step 293 corl_HTM = { 294 .shortname = "corl", 295 .name = "CO on R/L", 296 297 .final = false, 298 .is_done = check_coud_HTM, 299 .estimate = estimate_coud_HTM, 300 .ready = NULL, 301 .is_valid = validate_singlecw_ending, 302 .moveset = &moveset_HTM, 303 304 .pre_trans = rf, 305 306 .tables = {&pd_coud_HTM}, 307 .ntables = 1, 308 }; 309 310 Step 311 cofb_HTM = { 312 .shortname = "cofb", 313 .name = "CO on F/B", 314 315 .final = false, 316 .is_done = check_coud_HTM, 317 .estimate = estimate_coud_HTM, 318 .ready = NULL, 319 .is_valid = validate_singlecw_ending, 320 .moveset = &moveset_HTM, 321 322 .pre_trans = fd, 323 324 .tables = {&pd_coud_HTM}, 325 .ntables = 1, 326 }; 327 328 Step 329 coany_URF = { 330 .shortname = "co-URF", 331 .name = "CO any axis (URF moveset)", 332 333 .final = false, 334 .is_done = check_coud_URF, 335 .estimate = estimate_coud_URF, 336 .ready = NULL, 337 .is_valid = validate_singlecw_ending, 338 .moveset = &moveset_URF, 339 340 .detect = detect_pretrans_void_3axis, 341 342 .tables = {&pd_coud_HTM}, 343 .ntables = 1, 344 }; 345 346 Step 347 coud_URF = { 348 .shortname = "coud-URF", 349 .name = "CO on U/D (URF moveset)", 350 351 .final = false, 352 .is_done = check_coud_URF, 353 .estimate = estimate_coud_URF, 354 .ready = NULL, 355 .is_valid = validate_singlecw_ending, 356 .moveset = &moveset_URF, 357 358 .pre_trans = uf, 359 360 .tables = {&pd_coud_HTM}, 361 .ntables = 1, 362 }; 363 364 Step 365 corl_URF = { 366 .shortname = "corl-URF", 367 .name = "CO on R/L (URF moveset)", 368 369 .final = false, 370 .is_done = check_coud_URF, 371 .estimate = estimate_coud_URF, 372 .ready = NULL, 373 .is_valid = validate_singlecw_ending, 374 .moveset = &moveset_URF, 375 376 .pre_trans = rf, 377 378 .tables = {&pd_coud_HTM}, 379 .ntables = 1, 380 }; 381 382 Step 383 cofb_URF = { 384 .shortname = "cofb-URF", 385 .name = "CO on F/B (URF moveset)", 386 387 .final = false, 388 .is_done = check_coud_URF, 389 .estimate = estimate_coud_URF, 390 .ready = NULL, 391 .is_valid = validate_singlecw_ending, 392 .moveset = &moveset_URF, 393 394 .pre_trans = fd, 395 396 .tables = {&pd_coud_HTM}, 397 .ntables = 1, 398 }; 399 400 /* Misc corner steps *****************/ 401 Step 402 cornershtr_HTM = { 403 .shortname = "chtr", 404 .name = "Solve corners to HTR state", 405 406 .final = false, 407 .is_done = check_cornershtr, 408 .estimate = estimate_cornershtr_HTM, 409 .ready = NULL, 410 .is_valid = validate_htr, 411 .moveset = &moveset_HTM, 412 413 .pre_trans = uf, 414 415 .tables = {&pd_cornershtr_HTM}, 416 .ntables = 1, 417 }; 418 419 Step 420 cornershtr_URF = { 421 .shortname = "chtr-URF", 422 .name = "Solve corners to HTR state (URF moveset)", 423 424 .final = false, 425 .is_done = check_cornershtr, 426 .estimate = estimate_cornershtr_URF, 427 .ready = NULL, 428 .is_valid = validate_singlecw_ending, 429 .moveset = &moveset_URF, 430 431 .pre_trans = uf, 432 433 .tables = {&pd_cornershtr_HTM}, 434 .ntables = 1, 435 }; 436 437 Step 438 corners_HTM = { 439 .shortname = "corners", 440 .name = "Solve corners", 441 442 .final = true, 443 .is_done = check_corners_HTM, 444 .estimate = estimate_corners_HTM, 445 .ready = NULL, 446 .is_valid = always_valid, 447 .moveset = &moveset_HTM, 448 449 .pre_trans = uf, 450 451 .tables = {&pd_corners_HTM}, 452 .ntables = 1, 453 }; 454 455 Step 456 corners_URF = { 457 .shortname = "corners-URF", 458 .name = "Solve corners (URF moveset)", 459 460 .final = true, /* TODO: check if this works with reorient */ 461 .is_done = check_corners_URF, 462 .estimate = estimate_corners_URF, 463 .ready = NULL, 464 .is_valid = always_valid, 465 .moveset = &moveset_URF, 466 467 .pre_trans = uf, 468 469 .tables = {&pd_corners_HTM}, 470 .ntables = 1, 471 }; 472 473 /* DR steps **************************/ 474 Step 475 drany_HTM = { 476 .shortname = "dr", 477 .name = "DR on any axis", 478 479 .final = false, 480 .is_done = check_drud, 481 .estimate = estimate_drud_HTM, 482 .ready = check_centers, 483 .ready_msg = check_centers_msg, 484 .is_valid = validate_singlecw_ending, 485 .moveset = &moveset_HTM, 486 487 .detect = detect_pretrans_void_3axis, 488 489 .tables = {&pd_drud_sym16_HTM}, 490 .ntables = 1, 491 }; 492 493 Step 494 drud_HTM = { 495 .shortname = "drud", 496 .name = "DR on U/D", 497 498 .final = false, 499 .is_done = check_drud, 500 .estimate = estimate_drud_HTM, 501 .ready = check_centers, 502 .ready_msg = check_centers_msg, 503 .is_valid = validate_singlecw_ending, 504 .moveset = &moveset_HTM, 505 506 .pre_trans = uf, 507 508 .tables = {&pd_drud_sym16_HTM}, 509 .ntables = 1, 510 }; 511 512 Step 513 drrl_HTM = { 514 .shortname = "drrl", 515 .name = "DR on R/L", 516 517 .final = false, 518 .is_done = check_drud, 519 .estimate = estimate_drud_HTM, 520 .ready = check_centers, 521 .ready_msg = check_centers_msg, 522 .is_valid = validate_singlecw_ending, 523 .moveset = &moveset_HTM, 524 525 .pre_trans = rf, 526 527 .tables = {&pd_drud_sym16_HTM}, 528 .ntables = 1, 529 }; 530 531 Step 532 drfb_HTM = { 533 .shortname = "drfb", 534 .name = "DR on F/B", 535 536 .final = false, 537 .is_done = check_drud, 538 .estimate = estimate_drud_HTM, 539 .ready = check_centers, 540 .ready_msg = check_centers_msg, 541 .is_valid = validate_singlecw_ending, 542 .moveset = &moveset_HTM, 543 544 .pre_trans = fd, 545 546 .tables = {&pd_drud_sym16_HTM}, 547 .ntables = 1, 548 }; 549 550 /* DR from EO */ 551 Step 552 dr_eo = { 553 .shortname = "dr-eo", 554 .name = "DR without breaking EO (automatically detected)", 555 556 .final = false, 557 .is_done = check_drud_or_drrl, 558 .estimate = estimate_dr_eofb, 559 .ready = check_eofb, 560 .ready_msg = check_eo_msg, 561 .is_valid = validate_singlecw_ending, 562 .moveset = &moveset_eofb, 563 564 .detect = detect_pretrans_eofb, 565 566 .tables = {&pd_drud_eofb}, 567 .ntables = 1, 568 }; 569 570 Step 571 dr_eofb = { 572 .shortname = "dr-eofb", 573 .name = "DR on U/D or R/L without breaking EO on F/B", 574 575 .final = false, 576 .is_done = check_drud_or_drrl, 577 .estimate = estimate_dr_eofb, 578 .ready = check_eofb, 579 .ready_msg = check_eo_msg, 580 .is_valid = validate_singlecw_ending, 581 .moveset = &moveset_eofb, 582 583 .pre_trans = uf, 584 585 .tables = {&pd_drud_eofb}, 586 .ntables = 1, 587 }; 588 589 Step 590 dr_eorl = { 591 .shortname = "dr-eorl", 592 .name = "DR on U/D or F/B without breaking EO on R/L", 593 594 .final = false, 595 .is_done = check_drud_or_drrl, 596 .estimate = estimate_dr_eofb, 597 .ready = check_eofb, 598 .ready_msg = check_eo_msg, 599 .is_valid = validate_singlecw_ending, 600 .moveset = &moveset_eofb, 601 602 .pre_trans = ur, 603 604 .tables = {&pd_drud_eofb}, 605 .ntables = 1, 606 }; 607 608 Step 609 dr_eoud = { 610 .shortname = "dr-eoud", 611 .name = "DR on R/L or F/B without breaking EO on U/D", 612 613 .final = false, 614 .is_done = check_drud_or_drrl, 615 .estimate = estimate_dr_eofb, 616 .ready = check_eofb, 617 .ready_msg = check_eo_msg, 618 .is_valid = validate_singlecw_ending, 619 .moveset = &moveset_eofb, 620 621 .pre_trans = fd, 622 623 .tables = {&pd_drud_eofb}, 624 .ntables = 1, 625 }; 626 627 Step 628 drud_eofb = { 629 .shortname = "drud-eofb", 630 .name = "DR on U/D without breaking EO on F/B", 631 632 .final = false, 633 .is_done = check_drud, 634 .estimate = estimate_drud_eofb, 635 .ready = check_eofb, 636 .ready_msg = check_eo_msg, 637 .is_valid = validate_singlecw_ending, 638 .moveset = &moveset_eofb, 639 640 .pre_trans = uf, 641 642 .tables = {&pd_drud_eofb}, 643 .ntables = 1, 644 }; 645 646 Step 647 drrl_eofb = { 648 .shortname = "drrl-eofb", 649 .name = "DR on R/L without breaking EO on F/B", 650 651 .final = false, 652 .is_done = check_drud, 653 .estimate = estimate_drud_eofb, 654 .ready = check_eofb, 655 .ready_msg = check_eo_msg, 656 .is_valid = validate_singlecw_ending, 657 .moveset = &moveset_eofb, 658 659 .pre_trans = rf, 660 661 .tables = {&pd_drud_eofb}, 662 .ntables = 1, 663 }; 664 665 Step 666 drud_eorl = { 667 .shortname = "drud-eorl", 668 .name = "DR on U/D without breaking EO on R/L", 669 670 .final = false, 671 .is_done = check_drud, 672 .estimate = estimate_drud_eofb, 673 .ready = check_eofb, 674 .ready_msg = check_eo_msg, 675 .is_valid = validate_singlecw_ending, 676 .moveset = &moveset_eofb, 677 678 .pre_trans = ur, 679 680 .tables = {&pd_drud_eofb}, 681 .ntables = 1, 682 }; 683 684 Step 685 drfb_eorl = { 686 .shortname = "drfb-eorl", 687 .name = "DR on F/B without breaking EO on R/L", 688 689 .final = false, 690 .is_done = check_drud, 691 .estimate = estimate_drud_eofb, 692 .ready = check_eofb, 693 .ready_msg = check_eo_msg, 694 .is_valid = validate_singlecw_ending, 695 .moveset = &moveset_eofb, 696 697 .pre_trans = fr, 698 699 .tables = {&pd_drud_eofb}, 700 .ntables = 1, 701 }; 702 703 Step 704 drfb_eoud = { 705 .shortname = "drfb-eoud", 706 .name = "DR on F/B without breaking EO on U/D", 707 708 .final = false, 709 .is_done = check_drud, 710 .estimate = estimate_drud_eofb, 711 .ready = check_eofb, 712 .ready_msg = check_eo_msg, 713 .is_valid = validate_singlecw_ending, 714 .moveset = &moveset_eofb, 715 716 .pre_trans = fd, 717 718 .tables = {&pd_drud_eofb}, 719 .ntables = 1, 720 }; 721 722 Step 723 drrl_eoud = { 724 .shortname = "drrl-eoud", 725 .name = "DR on R/L without breaking EO on U/D", 726 727 .final = false, 728 .is_done = check_drud, 729 .estimate = estimate_drud_eofb, 730 .ready = check_eofb, 731 .ready_msg = check_eo_msg, 732 .is_valid = validate_singlecw_ending, 733 .moveset = &moveset_eofb, 734 735 .pre_trans = rd, 736 737 .tables = {&pd_drud_eofb}, 738 .ntables = 1, 739 }; 740 741 /* DR finish minus slice steps */ 742 Step 743 dranyslice_DR = { 744 .shortname = "drslice", 745 .name = "DR finish minus slice on any axis without breaking DR", 746 747 .final = true, 748 .is_done = check_drudslice, 749 .estimate = estimate_drudslice_drud, 750 .ready = check_drud, 751 .ready_msg = check_drany_msg, 752 .is_valid = always_valid, 753 .moveset = &moveset_drud_noD, 754 755 .detect = detect_pretrans_drud, 756 757 .tables = {&pd_drudfin_noE_sym16_drud}, 758 .ntables = 1, 759 }; 760 761 Step 762 drudslice_drud = { 763 .shortname = "drudslice", 764 .name = "DR finish minus slice on U/D without breaking DR", 765 766 .final = true, 767 .is_done = check_drudslice, 768 .estimate = estimate_drudslice_drud, 769 .ready = check_drud, 770 .ready_msg = check_dr_msg, 771 .is_valid = always_valid, 772 .moveset = &moveset_drud_noD, 773 774 .pre_trans = uf, 775 776 .tables = {&pd_drudfin_noE_sym16_drud}, 777 .ntables = 1, 778 }; 779 780 Step 781 drrlslice_drrl = { 782 .shortname = "drrlslice", 783 .name = "DR finish minus slice on R/L without breaking DR", 784 785 .final = true, 786 .is_done = check_drudslice, 787 .estimate = estimate_drudslice_drud, 788 .ready = check_drud, 789 .ready_msg = check_dr_msg, 790 .is_valid = always_valid, 791 .moveset = &moveset_drud_noD, 792 793 .pre_trans = rf, 794 795 .tables = {&pd_drudfin_noE_sym16_drud}, 796 .ntables = 1, 797 }; 798 799 Step 800 drfbslice_drfb = { 801 .shortname = "drfbslice", 802 .name = "DR finish minus slice on F/B without breaking DR", 803 804 .final = true, 805 .is_done = check_drudslice, 806 .estimate = estimate_drudslice_drud, 807 .ready = check_drud, 808 .ready_msg = check_dr_msg, 809 .is_valid = always_valid, 810 .moveset = &moveset_drud_noD, 811 812 .pre_trans = fd, 813 814 .tables = {&pd_drudfin_noE_sym16_drud}, 815 .ntables = 1, 816 }; 817 818 /* DR finish steps */ 819 Step 820 dranyfin_DR = { 821 .shortname = "drfin", 822 .name = "DR finish on any axis without breaking DR", 823 824 .final = true, 825 .is_done = is_solved, 826 .estimate = estimate_drudfin_drud, 827 .ready = check_drud, 828 .ready_msg = check_drany_msg, 829 .is_valid = always_valid, 830 .moveset = &moveset_drud, 831 832 .detect = detect_pretrans_drud, 833 834 .tables = {&pd_drudfin_noE_sym16_drud}, 835 .ntables = 1, 836 }; 837 838 Step 839 drudfin_drud = { 840 .shortname = "drudfin", 841 .name = "DR finish on U/D without breaking DR", 842 843 .final = true, 844 .is_done = is_solved, 845 .estimate = estimate_drudfin_drud, 846 .ready = check_drud, 847 .ready_msg = check_dr_msg, 848 .is_valid = always_valid, 849 .moveset = &moveset_drud, 850 851 .pre_trans = uf, 852 853 .tables = {&pd_drudfin_noE_sym16_drud}, 854 .ntables = 1, 855 }; 856 857 Step 858 drrlfin_drrl = { 859 .shortname = "drrlfin", 860 .name = "DR finish on R/L without breaking DR", 861 862 .final = true, 863 .is_done = is_solved, 864 .estimate = estimate_drudfin_drud, 865 .ready = check_drud, 866 .ready_msg = check_dr_msg, 867 .is_valid = always_valid, 868 .moveset = &moveset_drud, 869 870 .pre_trans = rf, 871 872 .tables = {&pd_drudfin_noE_sym16_drud}, 873 .ntables = 1, 874 }; 875 876 Step 877 drfbfin_drfb = { 878 .shortname = "drfbfin", 879 .name = "DR finish on F/B without breaking DR", 880 881 .final = true, 882 .is_done = is_solved, 883 .estimate = estimate_drudfin_drud, 884 .ready = check_drud, 885 .ready_msg = check_dr_msg, 886 .is_valid = always_valid, 887 .moveset = &moveset_drud, 888 889 .pre_trans = fd, 890 891 .tables = {&pd_drudfin_noE_sym16_drud}, 892 .ntables = 1, 893 }; 894 895 /* HTR from DR */ 896 Step 897 htr_any = { 898 .shortname = "htr", 899 .name = "HTR from DR", 900 901 .final = false, 902 .is_done = check_htr, 903 .estimate = estimate_htr_drud, 904 .ready = check_drud, 905 .ready_msg = check_drany_msg, 906 .is_valid = validate_htr, 907 .moveset = &moveset_drud, 908 909 .detect = detect_pretrans_drud, 910 911 .tables = {&pd_htr_drud}, 912 .ntables = 1, 913 }; 914 915 Step 916 htr_drud = { 917 .shortname = "htr-drud", 918 .name = "HTR from DR on U/D", 919 920 .final = false, 921 .is_done = check_htr, 922 .estimate = estimate_htr_drud, 923 .ready = check_drud, 924 .ready_msg = check_dr_msg, 925 .is_valid = validate_htr, 926 .moveset = &moveset_drud, 927 928 .pre_trans = uf, 929 930 .tables = {&pd_htr_drud}, 931 .ntables = 1, 932 }; 933 934 Step 935 htr_drrl = { 936 .shortname = "htr-drrl", 937 .name = "HTR from DR on R/L", 938 939 .final = false, 940 .is_done = check_htr, 941 .estimate = estimate_htr_drud, 942 .ready = check_drud, 943 .ready_msg = check_dr_msg, 944 .is_valid = validate_htr, 945 .moveset = &moveset_drud, 946 947 .pre_trans = rf, 948 949 .tables = {&pd_htr_drud}, 950 .ntables = 1, 951 }; 952 953 Step 954 htr_drfb = { 955 .shortname = "htr-drfb", 956 .name = "HTR from DR on F/B", 957 958 .final = false, 959 .is_done = check_htr, 960 .estimate = estimate_htr_drud, 961 .ready = check_drud, 962 .ready_msg = check_dr_msg, 963 .is_valid = validate_htr, 964 .moveset = &moveset_drud, 965 966 .pre_trans = fd, 967 968 .tables = {&pd_htr_drud}, 969 .ntables = 1, 970 }; 971 972 /* Corners from DR */ 973 Step 974 corners_dr_any = { 975 .shortname = "corners-dr", 976 .name = "Solve corners from DR", 977 978 .final = true, 979 .is_done = check_corners_HTM, 980 .estimate = estimate_cp_drud, 981 .ready = check_coud_HTM, 982 .ready_msg = check_coany_msg, 983 .is_valid = always_valid, 984 .moveset = &moveset_drud, 985 986 .detect = detect_pretrans_drud, 987 988 .tables = {&pd_cp_drud}, 989 .ntables = 1, 990 }; 991 992 Step 993 corners_drud = { 994 .shortname = "corners-drud", 995 .name = "Solve corners from DR on U/D", 996 997 .final = true, 998 .is_done = check_corners_HTM, 999 .estimate = estimate_cp_drud, 1000 .ready = check_coud_HTM, 1001 .ready_msg = check_co_msg, 1002 .is_valid = always_valid, 1003 .moveset = &moveset_drud, 1004 1005 .pre_trans = uf, 1006 1007 .tables = {&pd_cp_drud}, 1008 .ntables = 1, 1009 }; 1010 1011 Step 1012 corners_drrl = { 1013 .shortname = "corners-drrl", 1014 .name = "Solve corners from DR on R/L", 1015 1016 .final = true, 1017 .is_done = check_corners_HTM, 1018 .estimate = estimate_cp_drud, 1019 .ready = check_coud_HTM, 1020 .ready_msg = check_co_msg, 1021 .is_valid = always_valid, 1022 .moveset = &moveset_drud, 1023 1024 .pre_trans = rf, 1025 1026 .tables = {&pd_cp_drud}, 1027 .ntables = 1, 1028 }; 1029 1030 Step 1031 corners_drfb = { 1032 .shortname = "corners-drfb", 1033 .name = "Solve corners from DR on F/B", 1034 1035 .final = true, 1036 .is_done = check_corners_HTM, 1037 .estimate = estimate_cp_drud, 1038 .ready = check_coud_HTM, 1039 .ready_msg = check_co_msg, 1040 .is_valid = always_valid, 1041 .moveset = &moveset_drud, 1042 1043 .pre_trans = fd, 1044 1045 .tables = {&pd_cp_drud}, 1046 .ntables = 1, 1047 }; 1048 1049 /* HTR finish */ 1050 Step 1051 htrfin_htr = { 1052 .shortname = "htrfin", 1053 .name = "HTR finish without breaking HTR", 1054 1055 .final = true, 1056 .is_done = is_solved, 1057 .estimate = estimate_htrfin_htr, 1058 .ready = check_htr, 1059 .ready_msg = check_htr_msg, 1060 .is_valid = always_valid, 1061 .moveset = &moveset_htr, 1062 1063 .pre_trans = uf, 1064 1065 .tables = {&pd_htrfin_htr}, 1066 .ntables = 1, 1067 }; 1068 1069 Step *steps[] = { 1070 &optimal_HTM, /* first is default */ 1071 &optimal_light_HTM, 1072 1073 &eofin_eo, 1074 &eofbfin_eofb, 1075 &eorlfin_eorl, 1076 &eoudfin_eoud, 1077 1078 &eoany_HTM, 1079 &eofb_HTM, 1080 &eorl_HTM, 1081 &eoud_HTM, 1082 1083 &coany_HTM, 1084 &coud_HTM, 1085 &corl_HTM, 1086 &cofb_HTM, 1087 1088 &coany_URF, 1089 &coud_URF, 1090 &corl_URF, 1091 &cofb_URF, 1092 1093 &drany_HTM, 1094 &drud_HTM, 1095 &drrl_HTM, 1096 &drfb_HTM, 1097 1098 &dr_eo, 1099 &dr_eofb, 1100 &dr_eorl, 1101 &dr_eoud, 1102 &drud_eofb, 1103 &drrl_eofb, 1104 &drud_eorl, 1105 &drfb_eorl, 1106 &drfb_eoud, 1107 &drrl_eoud, 1108 1109 &dranyfin_DR, 1110 &drudfin_drud, 1111 &drrlfin_drrl, 1112 &drfbfin_drfb, 1113 1114 &dranyslice_DR, 1115 &drudslice_drud, 1116 &drrlslice_drrl, 1117 &drfbslice_drfb, 1118 1119 &htr_any, 1120 &htr_drud, 1121 &htr_drrl, 1122 &htr_drfb, 1123 1124 &corners_dr_any, 1125 &corners_drud, 1126 &corners_drrl, 1127 &corners_drfb, 1128 1129 &htrfin_htr, 1130 1131 &cornershtr_HTM, 1132 &cornershtr_URF, 1133 &corners_HTM, 1134 &corners_URF, 1135 1136 NULL 1137 }; 1138 1139 /* Checkers, estimators and validators ***************************************/ 1140 1141 static bool 1142 check_centers(Cube cube) 1143 { 1144 return cube.cpos == 0; 1145 } 1146 1147 static bool 1148 check_coud_HTM(Cube cube) 1149 { 1150 return cube.coud == 0; 1151 } 1152 1153 static bool 1154 check_coud_URF(Cube cube) 1155 { 1156 Cube c2, c3; 1157 1158 c2 = apply_move(z, cube); 1159 c3 = apply_move(x, cube); 1160 1161 return cube.coud == 0 || c2.coud == 0 || c3.coud == 0; 1162 } 1163 1164 static bool 1165 check_corners_URF(Cube cube) 1166 { 1167 Cube c; 1168 Trans i; 1169 1170 for (i = 0; i < NROTATIONS; i++) { 1171 c = apply_alg(rotation_alg(i), cube); 1172 if (c.cp && c.coud) 1173 return true; 1174 } 1175 1176 return false; 1177 } 1178 1179 static bool 1180 check_corners_HTM(Cube cube) 1181 { 1182 return cube.cp == 0 && cube.coud == 0; 1183 } 1184 1185 static bool 1186 check_cornershtr(Cube cube) 1187 { 1188 return coord_cornershtr.index(cube) == 0; 1189 } 1190 1191 static bool 1192 check_eofb(Cube cube) 1193 { 1194 return cube.eofb == 0; 1195 } 1196 1197 static bool 1198 check_drud(Cube cube) 1199 { 1200 return cube.eofb == 0 && cube.eorl == 0 && cube.coud == 0; 1201 } 1202 1203 static bool 1204 check_drud_or_drrl(Cube cube) 1205 { 1206 return check_drud(cube) || check_drud(apply_trans(rf, cube)); 1207 } 1208 1209 static bool 1210 check_htr(Cube cube) 1211 { 1212 return check_drud(cube) && coord_htr_drud.index(cube) == 0; 1213 } 1214 1215 static bool 1216 check_drudslice(Cube cube) 1217 { 1218 int i; 1219 Cube aux; 1220 1221 aux = cube; 1222 for (i = 0; i < 4; i++, aux = apply_move(y, aux)) 1223 if (coord_cp.index(aux) == 0 && 1224 coord_epud.index(aux) == 0) 1225 return true; 1226 1227 return false; 1228 } 1229 1230 static int 1231 estimate_eofb_HTM(DfsArg *arg) 1232 { 1233 return ptableval(&pd_eofb_HTM, arg->cube); 1234 } 1235 1236 static int 1237 estimate_coud_HTM(DfsArg *arg) 1238 { 1239 return ptableval(&pd_coud_HTM, arg->cube); 1240 } 1241 1242 static int 1243 estimate_coud_URF(DfsArg *arg) 1244 { 1245 /* TODO: I can improve this by checking first the orientation of 1246 * the corner in DBL and use that as a reference */ 1247 1248 Cube c; 1249 1250 c = arg->cube; 1251 1252 int ud = estimate_coud_HTM(arg); 1253 arg->cube = apply_move(z, c); 1254 int rl = estimate_coud_HTM(arg); 1255 arg->cube = apply_move(x, c); 1256 int fb = estimate_coud_HTM(arg); 1257 1258 arg->cube = c; 1259 1260 return MIN(ud, MIN(rl, fb)); 1261 } 1262 1263 static int 1264 estimate_corners_HTM(DfsArg *arg) 1265 { 1266 return ptableval(&pd_corners_HTM, arg->cube); 1267 } 1268 1269 static int 1270 estimate_cornershtr_HTM(DfsArg *arg) 1271 { 1272 return ptableval(&pd_cornershtr_HTM, arg->cube); 1273 } 1274 1275 static int 1276 estimate_cornershtr_URF(DfsArg *arg) 1277 { 1278 /* TODO: I can improve this by checking first the corner in DBL 1279 * and use that as a reference */ 1280 1281 int ret; 1282 Cube c; 1283 Trans i; 1284 1285 c = arg->cube; 1286 ret = 15; 1287 1288 for (i = 0; i < NROTATIONS; i++) { 1289 arg->cube = apply_alg(rotation_alg(i), c); 1290 ret = MIN(ret, estimate_cornershtr_HTM(arg)); 1291 } 1292 1293 arg->cube = c; 1294 1295 return ret; 1296 } 1297 1298 static int 1299 estimate_corners_URF(DfsArg *arg) 1300 { 1301 /* TODO: I can improve this by checking first the corner in DBL 1302 * and use that as a reference */ 1303 1304 int ret; 1305 Cube c; 1306 Trans i; 1307 1308 c = arg->cube; 1309 ret = 15; 1310 1311 for (i = 0; i < NROTATIONS; i++) { 1312 arg->cube = apply_alg(rotation_alg(i), c); 1313 ret = MIN(ret, estimate_corners_HTM(arg)); 1314 } 1315 1316 arg->cube = c; 1317 1318 return ret; 1319 } 1320 1321 static int 1322 estimate_drud_HTM(DfsArg *arg) 1323 { 1324 return ptableval(&pd_drud_sym16_HTM, arg->cube); 1325 } 1326 1327 static int 1328 estimate_drud_eofb(DfsArg *arg) 1329 { 1330 return ptableval(&pd_drud_eofb, arg->cube); 1331 } 1332 1333 static int 1334 estimate_dr_eofb(DfsArg *arg) 1335 { 1336 int r1, r2; 1337 1338 r1 = ptableval(&pd_drud_eofb, arg->cube); 1339 r2 = ptableval(&pd_drud_eofb, apply_trans(rf, arg->cube)); 1340 1341 return MIN(r1, r2); 1342 } 1343 1344 static int 1345 estimate_drudfin_drud(DfsArg *arg) 1346 { 1347 int val = ptableval(&pd_drudfin_noE_sym16_drud, arg->cube); 1348 1349 if (val != 0) 1350 return val; 1351 1352 return arg->cube.epose % 24 == 0 ? 0 : 1; 1353 } 1354 1355 static int 1356 estimate_drudslice_drud(DfsArg *arg) 1357 { 1358 int i, ret = 20; 1359 Cube aux; 1360 1361 aux = arg->cube; 1362 for (i = 0; i < 4; i++, aux = apply_move(y, aux)) 1363 ret = MIN(ret, ptableval(&pd_drudfin_noE_sym16_drud, aux)); 1364 1365 return ret; 1366 } 1367 1368 static int 1369 estimate_htr_drud(DfsArg *arg) 1370 { 1371 return ptableval(&pd_htr_drud, arg->cube); 1372 } 1373 1374 static int 1375 estimate_cp_drud(DfsArg *arg) 1376 { 1377 return ptableval(&pd_cp_drud, arg->cube); 1378 } 1379 1380 static int 1381 estimate_htrfin_htr(DfsArg *arg) 1382 { 1383 return ptableval(&pd_htrfin_htr, arg->cube); 1384 } 1385 1386 static int 1387 estimate_nxopt31_HTM(DfsArg *arg) 1388 { 1389 return estimate_nxoptlike(arg, &pd_nxopt31_HTM); 1390 } 1391 1392 /* TODO: also use generic procedure for this */ 1393 static int 1394 estimate_light_HTM(DfsArg *arg) 1395 { 1396 int target, ret; 1397 Cube aux; 1398 1399 static const uint64_t udmask = (1<<U) | (1<<U2) | (1<<U3) | 1400 (1<<D) | (1<<D2) | (1<<D3); 1401 static const uint64_t rlmask = (1<<R) | (1<<R2) | (1<<R3) | 1402 (1<<L) | (1<<L2) | (1<<L3); 1403 static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) | 1404 (1<<B) | (1<<B2) | (1<<B3); 1405 static const uint64_t htmask = (1<<U2) | (1<<D2) | 1406 (1<<R2) | (1<<L2) | 1407 (1<<F2) | (1<<B2); 1408 1409 ret = -1; 1410 target = arg->d - arg->current_alg->len; 1411 arg->inverse = (Cube){0}; 1412 arg->badmovesinv = 0; 1413 arg->badmoves = 0; 1414 1415 /* Corners */ 1416 arg->ed->corners = ptableval(&pd_corners_HTM, arg->cube); 1417 UPDATECHECKSTOP(ret, arg->ed->corners, target); 1418 1419 /* Normal probing */ 1420 arg->ed->normal_ud = ptableval(&pd_drud_sym16_HTM, arg->cube); 1421 UPDATECHECKSTOP(ret, arg->ed->normal_ud, target); 1422 aux = apply_trans(fd, arg->cube); 1423 arg->ed->normal_fb = ptableval(&pd_drud_sym16_HTM, aux); 1424 UPDATECHECKSTOP(ret, arg->ed->normal_fb, target); 1425 aux = apply_trans(rf, arg->cube); 1426 arg->ed->normal_rl = ptableval(&pd_drud_sym16_HTM, aux); 1427 UPDATECHECKSTOP(ret, arg->ed->normal_rl, target); 1428 1429 /* If ret == 0, it's solved (corners + triple slice solved) */ 1430 if (ret == 0) 1431 return is_solved(arg->cube) ? 0 : 1; 1432 1433 /* Michel de Bondt's trick*/ 1434 if (arg->ed->normal_ud == arg->ed->normal_fb && 1435 arg->ed->normal_fb == arg->ed->normal_rl) { 1436 UPDATECHECKSTOP(ret, arg->ed->normal_ud + 1, target); 1437 } 1438 1439 /* Inverse probing */ 1440 if (!((1<<arg->last1) & htmask)) { 1441 aux = arg->inverse = inverse_cube(arg->cube); 1442 if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud==-1)) { 1443 arg->ed->inverse_ud = 1444 ptableval(&pd_drud_sym16_HTM, aux); 1445 } 1446 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); 1447 if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb==-1)) { 1448 aux = apply_trans(fd, arg->inverse); 1449 arg->ed->inverse_fb = 1450 ptableval(&pd_drud_sym16_HTM, aux); 1451 } 1452 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); 1453 if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl==-1)) { 1454 aux = apply_trans(rf, arg->inverse); 1455 arg->ed->inverse_rl = 1456 ptableval(&pd_drud_sym16_HTM, aux); 1457 } 1458 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); 1459 } else { 1460 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); 1461 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); 1462 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); 1463 } 1464 1465 /* Michel de Bondt's trick*/ 1466 if (arg->ed->inverse_ud == arg->ed->inverse_fb && 1467 arg->ed->inverse_fb == arg->ed->inverse_rl) { 1468 UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target); 1469 } 1470 1471 /* nxopt trick + half turn trick */ 1472 if (arg->ed->normal_ud == target) 1473 arg->badmovesinv |= udmask | htmask; 1474 if (arg->ed->normal_fb == target) 1475 arg->badmovesinv |= fbmask | htmask; 1476 if (arg->ed->normal_rl == target) 1477 arg->badmovesinv |= rlmask | htmask; 1478 1479 if (arg->ed->inverse_ud == target) 1480 arg->badmoves |= udmask | htmask; 1481 if (arg->ed->inverse_fb == target) 1482 arg->badmoves |= fbmask | htmask; 1483 if (arg->ed->inverse_rl == target) 1484 arg->badmoves |= rlmask | htmask; 1485 1486 return arg->ed->oldret = ret; 1487 } 1488 1489 static int 1490 estimate_nxoptlike(DfsArg *arg, PruneData *pd) 1491 { 1492 int target, ret; 1493 Cube aux; 1494 1495 static const uint64_t udmask = (1<<U) | (1<<U2) | (1<<U3) | 1496 (1<<D) | (1<<D2) | (1<<D3); 1497 static const uint64_t rlmask = (1<<R) | (1<<R2) | (1<<R3) | 1498 (1<<L) | (1<<L2) | (1<<L3); 1499 static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) | 1500 (1<<B) | (1<<B2) | (1<<B3); 1501 1502 ret = -1; 1503 target = arg->d - arg->current_alg->len; 1504 arg->inverse = (Cube){0}; 1505 arg->badmovesinv = 0; 1506 arg->badmoves = 0; 1507 1508 /* Corners */ 1509 arg->ed->corners = ptableval(&pd_corners_HTM, arg->cube); 1510 UPDATECHECKSTOP(ret, arg->ed->corners, target); 1511 1512 /* Normal probing */ 1513 arg->ed->normal_ud = ptableval(pd, arg->cube); 1514 UPDATECHECKSTOP(ret, arg->ed->normal_ud, target); 1515 aux = apply_trans(fd, arg->cube); 1516 arg->ed->normal_fb = ptableval(pd, aux); 1517 UPDATECHECKSTOP(ret, arg->ed->normal_fb, target); 1518 aux = apply_trans(rf, arg->cube); 1519 arg->ed->normal_rl = ptableval(pd, aux); 1520 UPDATECHECKSTOP(ret, arg->ed->normal_rl, target); 1521 1522 if (ret == 0) 1523 return arg->step->is_done(arg->cube) ? 0 : 1; 1524 1525 /* Michel de Bondt's trick*/ 1526 if (arg->ed->normal_ud == arg->ed->normal_fb && 1527 arg->ed->normal_fb == arg->ed->normal_rl) { 1528 UPDATECHECKSTOP(ret, arg->ed->normal_ud + 1, target); 1529 } 1530 1531 /* Inverse probing */ 1532 aux = arg->inverse = inverse_cube(arg->cube); 1533 if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud == -1)) { 1534 arg->ed->inverse_ud = ptableval(pd, aux); 1535 } 1536 UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); 1537 if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb == -1)) { 1538 aux = apply_trans(fd, arg->inverse); 1539 arg->ed->inverse_fb = ptableval(pd, aux); 1540 } 1541 UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); 1542 if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl == -1)) { 1543 aux = apply_trans(rf, arg->inverse); 1544 arg->ed->inverse_rl = ptableval(pd, aux); 1545 } 1546 UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); 1547 1548 /* Michel de Bondt's trick*/ 1549 if (arg->ed->inverse_ud == arg->ed->inverse_fb && 1550 arg->ed->inverse_fb == arg->ed->inverse_rl) { 1551 UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target); 1552 } 1553 1554 /* nxopt trick */ 1555 if (arg->ed->normal_ud == target) 1556 arg->badmovesinv |= udmask; 1557 if (arg->ed->normal_fb == target) 1558 arg->badmovesinv |= fbmask; 1559 if (arg->ed->normal_rl == target) 1560 arg->badmovesinv |= rlmask; 1561 1562 if (arg->ed->inverse_ud == target) 1563 arg->badmoves |= udmask; 1564 if (arg->ed->inverse_fb == target) 1565 arg->badmoves |= fbmask; 1566 if (arg->ed->inverse_rl == target) 1567 arg->badmoves |= rlmask; 1568 1569 return arg->ed->oldret = ret; 1570 } 1571 1572 static bool 1573 always_valid(Alg *alg) 1574 { 1575 return true; 1576 } 1577 1578 static bool 1579 validate_singlecw_ending(Alg *alg) 1580 { 1581 int i; 1582 bool nor, inv; 1583 Move l2 = NULLMOVE, l1 = NULLMOVE, l2i = NULLMOVE, l1i = NULLMOVE; 1584 1585 for (i = 0; i < alg->len; i++) { 1586 if (alg->inv[i]) { 1587 l2i = l1i; 1588 l1i = alg->move[i]; 1589 } else { 1590 l2 = l1; 1591 l1 = alg->move[i]; 1592 } 1593 } 1594 1595 nor = l1 ==base_move(l1) && (!commute(l1, l2) ||l2 ==base_move(l2)); 1596 inv = l1i==base_move(l1i) && (!commute(l1i,l2i)||l2i==base_move(l2i)); 1597 1598 return nor && inv; 1599 } 1600 1601 static bool 1602 validate_htr(Alg *alg) 1603 { 1604 int i, lastqt_n, lastqt_i; 1605 Move m, b; 1606 1607 if (!validate_singlecw_ending(alg)) 1608 return false; 1609 1610 lastqt_n = lastqt_i = -1; 1611 for (i = 0; i < alg->len; i++) { 1612 m = alg->move[i]; 1613 b = base_move(m); 1614 if (m == b+1) 1615 continue; 1616 if (alg->inv[i] && lastqt_i == -1) 1617 lastqt_i = i; 1618 if (!alg->inv[i]) 1619 lastqt_n = i; 1620 } 1621 1622 for (i = 0; i < alg->len; i++) 1623 if (base_move(alg->move[i]) == D && 1624 i != lastqt_i && i != lastqt_n) 1625 return false; 1626 1627 return true; 1628 } 1629 1630 /* Pre-transformation detectors **********************************************/ 1631 1632 static int 1633 detect_pretrans_eofb(Cube cube, Trans *ret) 1634 { 1635 int i, n; 1636 static Trans tt[3] = {uf, ur, fd}; 1637 1638 for (i = 0, n = 0; i < 3; i++) 1639 if (check_eofb(apply_trans(tt[i], cube))) 1640 ret[n++] = tt[i]; 1641 1642 return n; 1643 } 1644 1645 static int 1646 detect_pretrans_drud(Cube cube, Trans *ret) 1647 { 1648 int i, n; 1649 static Trans tt[3] = {uf, fr, rd}; 1650 1651 for (i = 0, n = 0; i < 3; i++) 1652 if (check_drud(apply_trans(tt[i], cube))) 1653 ret[n++] = tt[i]; 1654 1655 return n; 1656 } 1657 1658 static int 1659 detect_pretrans_void_3axis(Cube cube, Trans *ret) 1660 { 1661 ret[0] = uf; 1662 ret[1] = fr; 1663 ret[2] = rd; 1664 1665 return 3; 1666 } 1667 1668 /* Public functions **********************************************************/ 1669 1670 void 1671 copy_estimatedata(EstimateData *src, EstimateData *dst) 1672 { 1673 dst->corners = src->corners; 1674 dst->normal_ud = src->normal_ud; 1675 dst->normal_fb = src->normal_fb; 1676 dst->normal_rl = src->normal_rl; 1677 dst->inverse_ud = src->inverse_ud; 1678 dst->inverse_fb = src->inverse_fb; 1679 dst->inverse_rl = src->inverse_rl; 1680 dst->oldret = src->oldret; 1681 } 1682 1683 void 1684 invert_estimatedata(EstimateData *ed) 1685 { 1686 swap(&(ed->normal_ud), &(ed->inverse_ud)); 1687 swap(&(ed->normal_fb), &(ed->inverse_fb)); 1688 swap(&(ed->normal_rl), &(ed->inverse_rl)); 1689 } 1690 1691 void 1692 reset_estimatedata(EstimateData *ed) 1693 { 1694 ed->corners = -1; 1695 ed->normal_ud = -1; 1696 ed->normal_fb = -1; 1697 ed->normal_rl = -1; 1698 ed->inverse_ud = -1; 1699 ed->inverse_fb = -1; 1700 ed->inverse_rl = -1; 1701 ed->oldret = -1; 1702 } 1703 1704 void 1705 prepare_step(Step *step, SolveOptions *opts) 1706 { 1707 int i; 1708 1709 if (step->final && opts->nisstype != NORMAL) { 1710 opts->nisstype = NORMAL; 1711 fprintf(stderr, "Step is final, NISS not used" 1712 " (-N and -L ignored)\n"); 1713 } 1714 1715 for (i = 0; i < step->ntables; i++) { 1716 genptable(step->tables[i], opts->nthreads); 1717 if (step->tables[i]->compact) 1718 genptable(step->tables[i]->fallback, opts->nthreads); 1719 } 1720 }