Annotation of researchv9/X11/src/X.V11R1/clients/puzzle/puzzle.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.