Annotation of researchv9/X11/src/X.V11R1/clients/puzzle/puzzle.c, revision 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.