|
|
1.1 ! root 1: /* ! 2: * $Source: /orpheus/u1/X11/clients/puzzle/RCS/puzzle.c,v $ ! 3: * $Header: puzzle.c,v 1.1 87/09/08 17:27:13 swick Exp $ ! 4: */ ! 5: ! 6: #ifndef lint ! 7: static char *rcsid_puzzle_c = "$Header: puzzle.c,v 1.1 87/09/08 17:27:13 swick Exp $"; ! 8: #endif lint ! 9: ! 10: /** ! 11: ** Puzzle ! 12: ** ! 13: ** Don Bennett, HP Labs ! 14: ** ! 15: ** this is the code that does the real work to solve the ! 16: ** puzzle. (Commonly seen as a 4x4 grid of sliding pieces ! 17: ** numbered 1-15 with one empty space.) ! 18: ** ! 19: ** The idea for the solution algorithm - solving the puzzle ! 20: ** in layers working from the outside in - comes to me ! 21: ** indirectly from John Nagle. ! 22: **/ ! 23: ! 24: #include <setjmp.h> ! 25: ! 26: #define min(x,y) (((x)>(y))?(x):(y)) ! 27: ! 28: #define MAX_PLAN 1000 ! 29: ! 30: #define LEFT 0 ! 31: #define RIGHT 1 ! 32: #define UP 2 ! 33: #define DOWN 3 ! 34: ! 35: int other_dir[4] = { RIGHT, LEFT, DOWN, UP }; ! 36: ! 37: /** layer info macros -> (innermost 4 tiles are layer zero, ordinal goes up ! 38: ** as you move out) ! 39: ** layer_depth - returns number of (rows down),(cols across) the layer starts; ! 40: ** layer_width - number of blocks wide the layer is; ! 41: **/ ! 42: ! 43: #define layer_depth(l) (layers-1-(l)) ! 44: #define layer_width(l) (PuzzleSize - 2*layer_depth(l)) ! 45: ! 46: /** macros for finding the corners of each layer **/ ! 47: ! 48: #define UL(l) (layer_depth(l)*(PuzzleSize+1) + \ ! 49: ExtraRows*PuzzleWidth + ExtraColumns*(layers-(l))) ! 50: #define UR(l) (layer_depth(l)*(PuzzleSize+1) + layer_width(l) - 1 + \ ! 51: ExtraRows*PuzzleWidth + ExtraColumns*(layers-(l))) ! 52: #define LL(l) ((layer_depth(l)+layer_width(l)-1)*PuzzleSize+layer_depth(l)+ \ ! 53: ExtraRows*PuzzleSize + ExtraColumns*(PuzzleHeight+1+(l)-layers)) ! 54: #define LR(l) ((layer_depth(l)+layer_width(l)-1)*(PuzzleSize+1) + \ ! 55: ExtraRows*PuzzleSize + ExtraColumns*(PuzzleHeight+1+(l)-layers)) ! 56: ! 57: /** get the x and y coordinates of a location in the matrix **/ ! 58: ! 59: #define get_x(loc) ((loc) % PuzzleWidth) ! 60: #define get_y(loc) ((loc) / PuzzleWidth) ! 61: #define indx(x,y) (((y)*PuzzleWidth) + (x)) ! 62: ! 63: #define next_left(loc) (loc - 1) ! 64: #define next_right(loc) (loc + 1) ! 65: #define next_up(loc) (loc - PuzzleWidth) ! 66: #define next_down(loc) (loc + PuzzleWidth) ! 67: ! 68: #define sign(foo) (((foo)>0)?1:-1) ! 69: ! 70: int OutputLogging = 0; ! 71: ! 72: static int SolvingFlag = 0; ! 73: static int AbortSolvingFlag = 0; ! 74: ! 75: static int ExtraRows = 0; ! 76: static int ExtraColumns = 0; ! 77: ! 78: /** PuzzleSize MUST be a multiple of 2; **/ ! 79: extern int PuzzleSize; ! 80: extern int PuzzleWidth, PuzzleHeight; ! 81: ! 82: int layers; ! 83: ! 84: int *tmp_matrix; ! 85: int *target; ! 86: int *locked; ! 87: int *link; ! 88: int *position; ! 89: ! 90: int space_x, space_y; /** location of space in the position matrix **/ ! 91: ! 92: static jmp_buf solve_env; ! 93: ! 94: /** ! 95: ** this piece of code needs to be fixed if you want to use it ! 96: ** for non-square matrices; ! 97: **/ ! 98: print_matrix(mat) ! 99: int (*mat)[]; ! 100: { ! 101: int i,j; ! 102: ! 103: printf("\n"); ! 104: for (i=0; i<PuzzleHeight; i++) { ! 105: for (j=0; j<PuzzleWidth; j++) ! 106: printf(" %2d ",(*mat)[indx(j,i)]); ! 107: printf("\n"); ! 108: } ! 109: printf("\n"); ! 110: } ! 111: ! 112: find_piece(piece) ! 113: int piece; ! 114: { ! 115: int i; ! 116: ! 117: for (i=0; i<PuzzleWidth*PuzzleHeight; i++) ! 118: if (position[i] == piece) ! 119: return(i); ! 120: ! 121: printf("piece %d not found!\n",piece); ! 122: exit(1); ! 123: } ! 124: ! 125: move_space_to(loc) ! 126: int loc; ! 127: { ! 128: int i,current_dir,dist; ! 129: int plan[MAX_PLAN]; ! 130: ! 131: plan_move(indx(space_x,space_y),loc,plan); ! 132: current_dir = plan[1]; ! 133: dist = 0; ! 134: for (i=1; i<=plan[0]; i++) ! 135: if (plan[i] == current_dir) ! 136: dist++; ! 137: else if (plan[i] == other_dir[current_dir]) ! 138: dist--; ! 139: else { ! 140: move_space(current_dir,dist); ! 141: current_dir = plan[i]; ! 142: dist = 1; ! 143: } ! 144: move_space(current_dir,dist); ! 145: } ! 146: ! 147: move_piece(loc,target) ! 148: int loc,target; ! 149: { ! 150: int i; ! 151: int plan[MAX_PLAN]; ! 152: ! 153: plan_move(loc,target,plan); ! 154: for (i=1; i<=plan[0]; i++) ! 155: switch(plan[i]) { ! 156: case LEFT: locked[loc] = 1; ! 157: move_space_to(next_left(loc)); ! 158: locked[loc] = 0; ! 159: move_space_to(loc); ! 160: loc = next_left(loc); ! 161: break; ! 162: case RIGHT: locked[loc] = 1; ! 163: move_space_to(next_right(loc)); ! 164: locked[loc] = 0; ! 165: move_space_to(loc); ! 166: loc = next_right(loc); ! 167: break; ! 168: case UP: locked[loc] = 1; ! 169: move_space_to(next_up(loc)); ! 170: locked[loc] = 0; ! 171: move_space_to(loc); ! 172: loc = next_up(loc); ! 173: break; ! 174: case DOWN: locked[loc] = 1; ! 175: move_space_to(next_down(loc)); ! 176: locked[loc] = 0; ! 177: move_space_to(loc); ! 178: loc = next_down(loc); ! 179: break; ! 180: } ! 181: } ! 182: ! 183: plan_move(start_loc,end_loc,path) ! 184: int start_loc, end_loc; ! 185: int (*path)[]; ! 186: { ! 187: ! 188: #define QUEUE_SIZE 1000 ! 189: #define DIST(loc1,loc2) (abs(get_x(loc1) - get_x(loc2)) + abs(get_y(loc1) - get_y(loc2))) ! 190: ! 191: int i, next_loc, next_dist, chosen, found_path, move_num; ! 192: int loc_x, loc_y; ! 193: int loc_queue[QUEUE_SIZE]; ! 194: int loc_dist[QUEUE_SIZE]; ! 195: int loc_queue_used[QUEUE_SIZE]; ! 196: int queue_head, queue_tail; ! 197: int candidate[4]; ! 198: ! 199: found_path = 0; ! 200: ! 201: for (i=0; i<PuzzleWidth*PuzzleHeight; i++) { ! 202: tmp_matrix[i] = -locked[i]; ! 203: link[i] = -1; ! 204: } ! 205: ! 206: for (i=0; i<QUEUE_SIZE; i++) ! 207: loc_queue_used[i] = 0; ! 208: ! 209: queue_head = 0; ! 210: queue_tail = 0; ! 211: ! 212: loc_queue[0] = start_loc; ! 213: loc_dist[0] = DIST(end_loc,start_loc); ! 214: tmp_matrix[start_loc] = 1; ! 215: queue_tail++; ! 216: ! 217: /** if the selected element has a distance of zero, we've found it; ! 218: ** (This really isn't a queue, but rather a range of elements ! 219: ** to be searched for an element of the desired properties; ! 220: **/ ! 221: ! 222: /** as we search for a path, ! 223: ** LINK array is used to indicate the direction from which ! 224: ** we moved into a location; ! 225: ** TMP_MATRIX array is used to keep track of the move number; ! 226: **/ ! 227: ! 228: while(queue_head < queue_tail && !found_path) { ! 229: /** find the entry that ! 230: ** (1) has the smallest distance and ! 231: ** (2) has the smallest move number; ! 232: **/ ! 233: ! 234: next_loc = loc_queue[queue_head]; ! 235: next_dist = loc_dist[queue_head]; ! 236: chosen = queue_head; ! 237: ! 238: for (i=queue_head+1; i<queue_tail; i++) ! 239: if (!loc_queue_used[i] && ! 240: ( loc_dist[i] < next_dist) || ! 241: ( (loc_dist[i] == next_dist) && ! 242: (tmp_matrix[loc_queue[i]] < tmp_matrix[next_loc]) ! 243: )) { ! 244: next_loc = loc_queue[i]; ! 245: next_dist = loc_dist[i]; ! 246: chosen = i; ! 247: } ! 248: ! 249: if (next_dist == 0) { ! 250: found_path = 1; ! 251: break; ! 252: } ! 253: ! 254: loc_queue_used[chosen] = 1; ! 255: ! 256: /********************************/ ! 257: /** permute the chosen element **/ ! 258: /********************************/ ! 259: ! 260: candidate[0] = next_left(next_loc); ! 261: candidate[1] = next_right(next_loc); ! 262: candidate[2] = next_up(next_loc); ! 263: candidate[3] = next_down(next_loc); ! 264: ! 265: loc_x = get_x(next_loc); ! 266: loc_y = get_y(next_loc); ! 267: ! 268: if (loc_x == 0) candidate[0] = -1; ! 269: if (loc_x == PuzzleWidth-1) candidate[1] = -1; ! 270: if (loc_y == 0) candidate[2] = -1; ! 271: if (loc_y == PuzzleHeight-1) candidate[3] = -1; ! 272: ! 273: move_num = tmp_matrix[next_loc] + 1; ! 274: ! 275: for (i=0; i<4; i++) ! 276: if (candidate[i] != -1 && tmp_matrix[candidate[i]] == 0) { ! 277: tmp_matrix[candidate[i]] = move_num; ! 278: /** the next line works because the candidate index is ! 279: ** same as the direction moved to reach the candidate; ! 280: **/ ! 281: link[candidate[i]] = i; ! 282: loc_queue[queue_tail] = candidate[i]; ! 283: loc_dist[queue_tail] = DIST(end_loc,candidate[i]); ! 284: queue_tail++; ! 285: if (queue_tail == QUEUE_SIZE) goto broke; ! 286: } ! 287: ! 288: /***************************************************/ ! 289: /** delete used items from the front of the queue **/ ! 290: /***************************************************/ ! 291: ! 292: while(loc_queue_used[queue_head] && queue_head < queue_tail) ! 293: queue_head++; ! 294: } ! 295: ! 296: if (!found_path) { ! 297: printf("couldn't find a way to move (%d,%d) to (%d,%d).\n", ! 298: get_x(start_loc),get_y(start_loc), ! 299: get_x(end_loc),get_y(end_loc)); ! 300: #ifdef UNDEFINED ! 301: print_matrix(position); ! 302: printf("\n"); ! 303: print_matrix(locked); ! 304: printf("\n"); ! 305: #endif UNDEFINED ! 306: return(0); ! 307: } ! 308: ! 309: broke: if (queue_tail == QUEUE_SIZE) { ! 310: printf("it didn't work.\n"); ! 311: return(0); ! 312: } ! 313: ! 314: /** copy the path we found into the path array; ! 315: ** element 0 will contain the number of moves in the path; ! 316: **/ ! 317: ! 318: /** by the time we get there, next_loc is in the final location **/ ! 319: ! 320: (*path)[0] = tmp_matrix[next_loc] - 1; ! 321: for (i=(*path)[0]; i>0; i--) { ! 322: (*path)[i] = link[next_loc]; ! 323: switch(link[next_loc]) { ! 324: case LEFT: next_loc = next_right(next_loc); ! 325: break; ! 326: case RIGHT: next_loc = next_left(next_loc); ! 327: break; ! 328: case UP: next_loc = next_down(next_loc); ! 329: break; ! 330: case DOWN: next_loc = next_up(next_loc); ! 331: break; ! 332: } ! 333: } ! 334: } ! 335: ! 336: move_space(dir,dist) ! 337: int dir,dist; ! 338: { ! 339: int i, step, count; ! 340: int min_x,max_x,min_y,max_y; ! 341: int first_x,first_y; ! 342: int last_x,last_y, shift_dir; ! 343: ! 344: ! 345: if (PuzzlePending()) ProcessEvents(); ! 346: if (SolvingFlag && AbortSolvingFlag) ! 347: longjmp(solve_env,1); ! 348: ! 349: if (dist == 0) ! 350: return; ! 351: ! 352: if (dir == LEFT) { ! 353: dir = RIGHT; ! 354: dist = -dist; ! 355: } ! 356: ! 357: if (dir == UP) { ! 358: dir = DOWN; ! 359: dist = -dist; ! 360: } ! 361: ! 362: first_x = space_x; ! 363: first_y = space_y; ! 364: ! 365: step = 1; ! 366: count = dist; ! 367: if (dist < 0) { ! 368: step = -1; ! 369: count = -count; ! 370: } ! 371: ! 372: /** first_x,y are the location of the first piece to be shifted **/ ! 373: if (dir == RIGHT) ! 374: first_x += step; ! 375: else ! 376: first_y += step; ! 377: ! 378: /** shift_dir is the direction the pieces need to be shifted **/ ! 379: if (dist < 0) ! 380: shift_dir = dir; ! 381: else ! 382: switch (dir) { ! 383: case LEFT: shift_dir = RIGHT; break; ! 384: case RIGHT: shift_dir = LEFT; break; ! 385: case UP: shift_dir = DOWN; break; ! 386: case DOWN: shift_dir = UP; break; ! 387: } ! 388: ! 389: for (i=0; i<count; i++) ! 390: if (dir == RIGHT) { ! 391: position[indx(space_x,space_y)] = position[indx(space_x+step,space_y)]; ! 392: position[indx(space_x+step,space_y)] = 0; ! 393: space_x += step; ! 394: } ! 395: /** dir == DOWN **/ ! 396: else { ! 397: position[indx(space_x,space_y)] = position[indx(space_x,space_y+step)]; ! 398: position[indx(space_x,space_y+step)] = 0; ! 399: space_y += step; ! 400: } ! 401: ! 402: last_x = space_x; ! 403: last_y = space_y; ! 404: ! 405: /** the blocks first_x,y through last_x,y need to be shifted ! 406: ** one block in the shift_dir direction; ! 407: **/ ! 408: ! 409: if (OutputLogging) ! 410: LogMoveSpace(first_x,first_y,last_x,last_y,shift_dir); ! 411: } ! 412: ! 413: initialize() ! 414: { ! 415: /** Initialize the position and ! 416: ** the target matrices; ! 417: **/ ! 418: ! 419: int i; ! 420: int sp_x, sp_y; ! 421: ! 422: srand(42); ! 423: layers = PuzzleSize / 2; ! 424: ! 425: ExtraRows = PuzzleHeight - PuzzleSize; ! 426: ExtraColumns = PuzzleWidth - PuzzleSize; ! 427: ! 428: tmp_matrix = (int *) malloc(PuzzleWidth*PuzzleHeight*sizeof(int)); ! 429: target = (int *) malloc(PuzzleWidth*PuzzleHeight*sizeof(int)); ! 430: locked = (int *) malloc(PuzzleWidth*PuzzleHeight*sizeof(int)); ! 431: link = (int *) malloc(PuzzleWidth*PuzzleHeight*sizeof(int)); ! 432: position = (int *) malloc(PuzzleWidth*PuzzleHeight*sizeof(int)); ! 433: ! 434: for (i=0; i<PuzzleWidth*PuzzleHeight; i++) ! 435: locked[i] = 0; ! 436: ! 437: if (!tmp_matrix || !target || !locked || !link || !position) { ! 438: printf("matrix allocation failed.\n"); ! 439: exit(1); ! 440: } ! 441: ! 442: for (i=0; i<PuzzleWidth*PuzzleHeight-1; i++) { ! 443: target[i] = i+1; ! 444: position[i] = i+1; ! 445: } ! 446: ! 447: /** assert i == PuzzleWidth * PuzzleHeight - 1; **/ ! 448: position[i] = 0; ! 449: target[i] = 0; ! 450: ! 451: space_x = PuzzleWidth - 1; ! 452: space_y = PuzzleHeight - 1; ! 453: ! 454: ! 455: /** Move the space into the LR corner of the ! 456: ** innermost layer; ! 457: ** For each of the outer layers, move the space ! 458: ** left one and up one; ! 459: **/ ! 460: ! 461: sp_x = space_x; ! 462: sp_y = space_y; ! 463: ! 464: for (i=0; i<layers-1; i++) { ! 465: /** move the space left one; **/ ! 466: target[indx(sp_x,sp_y)] = target[indx(sp_x-1,sp_y)]; ! 467: target[indx(sp_x-1,sp_y)] = 0; ! 468: sp_x -= 1; ! 469: ! 470: /** move the space up one; **/ ! 471: target[indx(sp_x,sp_y)] = target[indx(sp_x,sp_y-1)]; ! 472: target[indx(sp_x,sp_y-1)] = 0; ! 473: sp_y -= 1; ! 474: } ! 475: } ! 476: ! 477: Scramble() ! 478: { ! 479: int i; ! 480: int new_x, new_y; ! 481: int old_output_state; ! 482: ! 483: old_output_state = OutputLogging; ! 484: OutputLogging = 0; ! 485: /* srand(42); */ ! 486: ! 487: ! 488: for (i=0; i<10*PuzzleWidth*PuzzleHeight; i++) { ! 489: new_x = rand() % PuzzleWidth; ! 490: new_y = rand() % PuzzleHeight; ! 491: ! 492: move_space(RIGHT,new_x-space_x); ! 493: move_space(DOWN,new_y-space_y); ! 494: } ! 495: ! 496: OutputLogging = old_output_state; ! 497: } ! 498: ! 499: /** To solve this puzzle, work from the outside in; ! 500: ** For each successive ring working your way in, ! 501: ** ! 502: ** (1) put the corners in place; ! 503: ** (2) finish off the rest of the boundaries; ! 504: ** (3) do the next layer in; ! 505: **/ ! 506: ! 507: solve_layer_0() ! 508: { ! 509: move_piece(find_piece(target[UL(0)]),UL(0)); ! 510: move_space_to(LR(0)); ! 511: } ! 512: ! 513: do_last_two_on_edge(ntlast,last,tmp,emergency) ! 514: int ntlast,last,tmp,emergency; ! 515: { ! 516: int last_piece, ntlast_piece; ! 517: last_piece = target[last]; ! 518: ntlast_piece = target[ntlast]; ! 519: ! 520: move_piece(find_piece(ntlast_piece),last); ! 521: locked[last] = 1; ! 522: ! 523: /** if the last piece is stuck where the next to the last ! 524: ** piece should go, do some magic to fix things up; ! 525: **/ ! 526: if (find_piece(0) == ntlast) ! 527: move_space_to(tmp); ! 528: ! 529: if (find_piece(last_piece) == ntlast) { ! 530: /** a rescue is necessary **/ ! 531: locked[last] = 0; ! 532: move_piece(find_piece(ntlast_piece),ntlast); ! 533: locked[ntlast] = 1; ! 534: move_piece(find_piece(last_piece),emergency); ! 535: locked[emergency] = 1; ! 536: locked[ntlast] = 0; ! 537: move_piece(find_piece(ntlast_piece),last); ! 538: locked[emergency] = 0; ! 539: locked[last] = 1; ! 540: } ! 541: ! 542: move_piece(find_piece(last_piece),tmp); ! 543: locked[tmp] = 1; ! 544: move_space_to(ntlast); ! 545: locked[tmp] = 0; ! 546: locked[last] = 0; ! 547: move_space_to(last); ! 548: move_space_to(tmp); ! 549: locked[ntlast] = 1; ! 550: locked[last] = 1; ! 551: } ! 552: ! 553: solve_layer(layer) ! 554: int layer; ! 555: { ! 556: int i, tmp, last, ntlast, emergency; ! 557: int ul, ur, ll, lr; ! 558: ! 559: ! 560: if (layer == 0) ! 561: solve_layer_0(); ! 562: else { ! 563: /** find and put each of the corners into place **/ ! 564: ul = UL(layer); ! 565: ur = UR(layer); ! 566: ll = LL(layer); ! 567: lr = LR(layer); ! 568: ! 569: move_piece(find_piece(target[ul]),ul); ! 570: locked[ul] = 1; ! 571: move_piece(find_piece(target[ur]),ur); ! 572: locked[ur] = 1; ! 573: move_piece(find_piece(target[ll]),ll); ! 574: locked[ll] = 1; ! 575: move_piece(find_piece(target[lr]),lr); ! 576: locked[lr] = 1; ! 577: ! 578: /** Strategy for doing the pieces between the corners: ! 579: ** (1) put all but the last two edge pieces in place; ! 580: ** (2) put the next to the last piece next to the corner; ! 581: ** (3) put the last piece one move in from its final position; ! 582: ** (4) move the space to the final position of the next ! 583: ** to the last piece; ! 584: ** (5) slide the next to the last piece over and the last ! 585: ** piece into the edge where it goes. ! 586: **/ ! 587: ! 588: /**************/ ! 589: /** top edge **/ ! 590: /**************/ ! 591: for (i=ul+1; i<ur-2; i++) { ! 592: move_piece(find_piece(target[i]),i); ! 593: locked[i] = 1; ! 594: } ! 595: ! 596: ntlast = i; ! 597: last = i+1; ! 598: tmp = UR(layer-1); ! 599: emergency = next_down(tmp); ! 600: do_last_two_on_edge(ntlast,last,tmp,emergency); ! 601: ! 602: /*****************/ ! 603: /** bottom edge **/ ! 604: /*****************/ ! 605: for (i=ll+1; i<lr-2; i++) { ! 606: move_piece(find_piece(target[i]),i); ! 607: locked[i] = 1; ! 608: } ! 609: ! 610: ntlast = i; ! 611: last = i+1; ! 612: tmp = LR(layer-1); ! 613: emergency = next_up(tmp); ! 614: do_last_two_on_edge(ntlast,last,tmp,emergency); ! 615: ! 616: /***************/ ! 617: /** left side **/ ! 618: /***************/ ! 619: for (i=ul+PuzzleWidth; i<ll-2*PuzzleWidth; i+=PuzzleWidth) { ! 620: move_piece(find_piece(target[i]),i); ! 621: locked[i] = 1; ! 622: } ! 623: ! 624: ntlast = i; ! 625: last = i + PuzzleWidth; ! 626: tmp = LL(layer-1); ! 627: emergency = next_right(tmp); ! 628: do_last_two_on_edge(ntlast,last,tmp,emergency); ! 629: ! 630: /****************/ ! 631: /** right side **/ ! 632: /****************/ ! 633: for (i=ur+PuzzleWidth; i<lr-2*PuzzleWidth; i+=PuzzleWidth) { ! 634: move_piece(find_piece(target[i]),i); ! 635: locked[i] = 1; ! 636: } ! 637: ! 638: ntlast = i; ! 639: last = i + PuzzleWidth; ! 640: tmp = LR(layer-1); ! 641: emergency = next_left(tmp); ! 642: do_last_two_on_edge(ntlast,last,tmp,emergency); ! 643: } ! 644: } ! 645: ! 646: solve_row(row) ! 647: int row; ! 648: { ! 649: int i, loc, last, ntlast, tmp, emergency; ! 650: ! 651: for (i=0; i<PuzzleWidth-2; i++) { ! 652: loc = indx(i,row); ! 653: move_piece(find_piece(target[loc]),loc); ! 654: locked[loc] = 1; ! 655: } ! 656: ! 657: ntlast = indx(PuzzleWidth-2,row); ! 658: last = indx(PuzzleWidth-1,row); ! 659: tmp = last + PuzzleWidth; ! 660: emergency = tmp + PuzzleWidth; ! 661: do_last_two_on_edge(ntlast,last,tmp,emergency); ! 662: } ! 663: ! 664: solve_col(col) ! 665: int col; ! 666: { ! 667: int i, loc, last, ntlast, tmp, emergency; ! 668: ! 669: for (i=0; i<PuzzleHeight-2; i++) { ! 670: loc = indx(col,i); ! 671: move_piece(find_piece(target[loc]),loc); ! 672: locked[loc] = 1; ! 673: } ! 674: ! 675: ntlast = indx(col,PuzzleHeight-2); ! 676: last = indx(col,PuzzleHeight-1); ! 677: tmp = last + 1; ! 678: emergency = tmp + 1; ! 679: do_last_two_on_edge(ntlast,last,tmp,emergency); ! 680: } ! 681: ! 682: AbortSolving() ! 683: { ! 684: if (SolvingFlag) ! 685: AbortSolvingFlag = 1; ! 686: } ! 687: ! 688: SolvingStatus() ! 689: { ! 690: return(SolvingFlag); ! 691: } ! 692: ! 693: Solve() ! 694: { ! 695: /** determine the position we want to be in when ! 696: ** we are done; This position will have the space in ! 697: ** the center; Then, we'll move the space back to ! 698: ** the outside. ! 699: **/ ! 700: ! 701: int i; ! 702: ! 703: ! 704: if (SolvingFlag) ! 705: return; ! 706: ! 707: if (!setjmp(solve_env)) { ! 708: SolvingFlag = 1; ! 709: ! 710: for (i=0; i<PuzzleWidth*PuzzleHeight; i++) ! 711: locked[i] = 0; ! 712: ! 713: /** solve the extra rows and cols **/ ! 714: for (i=0; i<ExtraRows; i++) ! 715: solve_row(i); ! 716: ! 717: for (i=0; i<ExtraColumns; i++) ! 718: solve_col(i); ! 719: ! 720: /** solve each layer **/ ! 721: for (i=layers-1; i>=0; i--) ! 722: solve_layer(i); ! 723: ! 724: /** move the space back out to the LR corner; **/ ! 725: /** i is the layer the space is moving into **/ ! 726: for (i=1; i<layers; i++) { ! 727: move_space(DOWN,1); ! 728: move_space(RIGHT,1); ! 729: } ! 730: } ! 731: else ! 732: RepaintTiles(); ! 733: ! 734: for (i=0; i<PuzzleWidth*PuzzleHeight; i++) ! 735: locked[i] = 0; ! 736: ! 737: AbortSolvingFlag = 0; ! 738: SolvingFlag = 0; ! 739: } ! 740: ! 741: #ifdef UNDEFINED ! 742: main() ! 743: { ! 744: #ifdef DEBUG ! 745: int plan[1000]; ! 746: int i; ! 747: #endif DEBUG ! 748: ! 749: initialize(); ! 750: ! 751: #ifdef DEBUG ! 752: print_matrix(position); ! 753: #endif DEBUG ! 754: ! 755: scramble(); ! 756: ! 757: #ifdef DEBUG ! 758: print_matrix(position); ! 759: ! 760: #ifdef UDEFINED ! 761: locked[indx(4,3)] = 1; ! 762: locked[indx(4,2)] = 1; ! 763: locked[indx(4,1)] = 1; ! 764: locked[indx(5,2)] = 1; ! 765: ! 766: plan_move(indx(space_x,space_y),indx(5,1),plan); ! 767: print_matrix(tmp_matrix); ! 768: printf("\nplan has %d moves.\n",plan[0]); ! 769: for (i=0; i<plan[0]; i++) { ! 770: switch(plan[i+1]) { ! 771: case UP: printf("up\n"); ! 772: break; ! 773: case DOWN: printf("down\n"); ! 774: break; ! 775: case LEFT: printf("left\n"); ! 776: break; ! 777: case RIGHT: printf("right\n"); ! 778: break; ! 779: } ! 780: } ! 781: #endif UDEFINED ! 782: #endif DEBUG ! 783: ! 784: solve(); ! 785: } ! 786: #endif UNDEFINED
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.